[
  {
    "path": ".gitignore",
    "content": "# Prerequisites\n*.d\n\n# Compiled Object files\n*.slo\n*.lo\n*.o\n*.obj\n\n# Precompiled Headers\n*.gch\n*.pch\n\n# Compiled Dynamic libraries\n*.so\n*.dylib\n*.dll\n\n# Fortran module files\n*.mod\n*.smod\n\n# Compiled Static libraries\n*.lai\n*.la\n*.a\n*.lib\n\n# Executables\n*.exe\n*.out\n*.app\n\nwifiRawReceiver/bin/\n\nwifiRawEcho/bin/\n\nESPNOW_lib/bin/\n\nESP32-Test/PYTHON_serial/test\\.txt\n\n*.txt\n\n*.pyc\n\n*.png\n\n*.pcapng\n\nESP32-Test/PYTHON_serial/channel_study\\.py\n\nESP32-Test/PYTHON_serial/datarate_study\\.py\n\nESP32-Test/PYTHON_serial/trash\n"
  },
  {
    "path": "ESP32-Test/ESP32-Test.ino",
    "content": "#include <esp_now.h>\n#include <WiFi.h>\n#include <esp_wifi_internal.h>\n\n#include <Ticker.h>  //Ticker Library\n\n#define CHANNEL 9\n#define DATARATE WIFI_PHY_RATE_24M\n\n#define N_BATCH 1000\n\nstatic byte dest_mac[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; //broadcast\n//static byte dest_mac[6] = {0xf8, 0x1a, 0x67, 0xb7, 0xeb, 0x0b}; //computers\n//static byte dest_mac[6] ={0x84, 0xF3, 0xEB, 0x73, 0x55, 0x1E}; //ESP8266 (2) Echo mode\n\nesp_now_peer_info_t peer;\nwifi_config_t wifi_config;\n\nTicker blinker;\n\n#define DATA_LEN 127\nuint8_t txData[DATA_LEN];\n\nvoid init_data() {\n  for(int i=0;i<DATA_LEN;i++) {\n    txData[i] = 0x14;\n  }\n}\n"
  },
  {
    "path": "ESP32-Test/PYTHON_serial/serial_logger.py",
    "content": "import serial\nimport sys\nimport matplotlib.pyplot as plt\nfrom matplotlib.ticker import MaxNLocator\n\nbase = \"0123456789+/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\";\n\nlog_file = None\nser = None\n\nn_plot = 0\n\nif(len(sys.argv)==3):\n\tlog_file = open(sys.argv[2],\"a+\")\n\tser = serial.Serial(sys.argv[1], 115200)\n\tser.flushInput()\n\nelif(len(sys.argv)==2):\n\tser = open(sys.argv[1],\"r\")\n\n\nassert(len(sys.argv)==2 or len(sys.argv)==3)\n\n\nprint \"Serial opened : \" + str(sys.argv[1])\n\n\ndef read(display=True):\n\tline = ser.readline().rstrip()\n\tif(log_file != None):\n\t\tlog_file.write(line + '\\n')\n\tif(display):\n\t\tprint('\\t' + line)\n\treturn line\n\ndef read_int(i):\n\treturn int(read().split('\\t')[i])\n\ndef decode_histo():\n\tunits = read().split('\\t')[1]\n\tbounds = list(map(int, read().split('\\t')[1:]))\n\tnb_values = read_int(1)\n\thisto = list(map(int, read(False).split('\\t')[1:]))\n\tavg = read_int(1)\n\trecv = read_int(1)\n\tsent = read_int(1)\n\trecv_detail = read(False)\n\n\tovertimed = histo[-1]\n\thisto = histo[:-1]\n\tnb_values = nb_values-1\n\n\tbounds = list(map(lambda x : x/1000., bounds))\n\tx_axis = [(x+0.5)*(bounds[1]-bounds[0])/nb_values+bounds[0] for x in range(nb_values)]\n\t\n\n\thisto_cumulate = [0 for i in range(len(histo))]\n\thisto_cumulate[0] = histo[0]\n\tfor i in range(1, len(histo)):\n\t\thisto_cumulate[i] = histo_cumulate[i-1] + histo[i]\n\n\thisto = list(map(lambda x:x*100./sent, histo))\n\thisto_cumulate = list(map(lambda x: x*100./sent, histo_cumulate))\n\n\n\thisto_loss = [0 for _ in range(20)]\n\tcurrent_serie = 0\n\n\tfor i in range(len(recv_detail)):\n\t\tword = base.index(recv_detail[i])\n\t\tfor j in range(6):\n\t\t\tif(word&(1<<j) == 0):\n\t\t\t\tcurrent_serie += 1\n\t\t\telse:\n\t\t\t\thisto_loss[current_serie] += 1\n\t\t\t\tcurrent_serie = 0\n\n\n\tx_axis_loss = [i for i in range(len(histo_loss))]\n\ttotal = 0\n\tfor h in histo_loss:\n\t\ttotal+=h\n\tprint(total)\n\n\tplt.ion()\n\n\tfig = plt.figure(2*n_plot)\n\tax1 = fig.add_subplot(111)\n\tax2 = ax1.twinx()\n\n\tplt.title('(' + str(n_plot) + ')' + 'Overall receive ' + str(recv*100./sent) + '% ; Sent : ' + str(sent) + ' ; Longer than ' + str(bounds[1]) + units + ' : ' + str(overtimed))\n\n\tax1.plot(x_axis, histo, color='tab:blue')\n\tax1.set_ylabel('% packets', color='tab:blue')\n\tax1.tick_params(axis='y', labelcolor='tab:blue')\n\tax1.set_yticks([i*0.5  for i in range(int(max(histo)+1)*2)])\n\n\tax1.set_xticks([i*(bounds[1]-bounds[0])/10.+bounds[0]  for i in range(11)])\n\n\n\tax2.plot(x_axis, histo_cumulate, color='tab:red')\n\tax2.set_ylabel('% packets', color='tab:red')\n\tax2.tick_params(axis='y', labelcolor='tab:red')\n\tax2.set_yticks([i*10  for i in range(11)])\n\n\tax2.plot([x_axis[0], x_axis[-1]], [95, 95], color='tab:orange')\n\n\tax1.set_xlabel('Delay ( 1000' + units + ') ; Avg = ' + str(avg) + units)\n\n\tfig.tight_layout()\n\tfig.legend([\"histogram\", \"cumulated\", \"95%\", \"hello\"])\n\tplt.grid()\n\n\tplt.plot()\n\n\n\n\n\tplt.ion()\n\n\tfig = plt.figure(2*n_plot+1)\n\tax = fig.add_subplot(111)\n\n\tplt.title('(' + str(n_plot) + ')' + 'Detail receive ')\n\n\tplt.bar(x_axis_loss,histo_loss)\n\tax.set_ylabel('# groups')\n\tax.set_xlabel('group size')\n\tax.set_xticks(x_axis_loss)\n\n\tplt.grid()\n\n\tplt.plot()\n\n\nwhile n_plot < 3:\n\tline = read(False)\n\tif(\"----------\" in line):\n\t\tn_plot+=1\n\t\tprint(\"\\033[31mHisto \" + str(n_plot) + \" \\033[31mreceived\\033[0m\")\n\t\tdecode_histo()\n\telse:\n\t\tprint(\"\\033[34mLine not recognized \\033[0m >> \\033[33m\" + line + \"\\033[0m\")\n\t\ntry :\n\traw_input(\"Press [enter] to continue.\")\nexcept:\n\tpass"
  },
  {
    "path": "ESP32-Test/p_histogram.ino",
    "content": "#define HISTO_INF 0\n#define HISTO_SUP 10000\n#define HISTO_N_STEP 100\n\n#define recv_list_len N_BATCH/6\n#define packet_received(p) recv_list[p/6] |= 1<<p%6\n\nchar base[64] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'};\nbyte recv_list[recv_list_len];\nint histogram[HISTO_N_STEP];\nint histogram_higher;\nint histogram_lower;\nint error_recv;\nint receiveNb;\nint error_send;\ndouble avg;\n\nlong batchStart =0;\n\nunsigned long n_sent;\n\nvoid init_histo() {\n  for(int i=0;i<recv_list_len;i++) {\n    recv_list[i] = 0;\n  }\n  for(int i=0;i<HISTO_N_STEP;i++) {\n    histogram[i] = 0;\n  }\n  histogram_higher = 0;\n  histogram_lower = 0;\n  error_recv=0;\n  error_send=0;\n  receiveNb=0;\n  avg=0;\n}\n\nint fill_histo(long value, int packet_nb) {\n  int index = (value-HISTO_INF) * HISTO_N_STEP / (HISTO_SUP - HISTO_INF);\n  if(index >= HISTO_N_STEP) {\n    histogram_higher++;\n  } else if(index < 0) {\n    histogram_lower++;\n  } else {\n    histogram[index]++;\n  }\n\n  packet_received(packet_nb);\n  receiveNb++;\n  avg += value;\n}\n\nvoid print_histo() {\n  Serial.println(\"----------\");\n  Serial.printf(\"Units :\\tus\");\n  Serial.println();\n  Serial.printf(\"Bounds :\\t%d\\t%d\", HISTO_INF, HISTO_SUP);\n  Serial.println();\n  Serial.printf(\"Nb_values :\\t%d\", HISTO_N_STEP);\n  Serial.println();\n  for(int i=0;i<HISTO_N_STEP;i++) {\n    Serial.printf(\"%d\\t\", histogram[i]);\n  }\n  Serial.printf(\"%d\",histogram_higher);\n  \n  Serial.println();\n  Serial.printf(\"Average :\\t%d\\t\", receiveNb != 0 ? int(avg/receiveNb) : -1);\n  Serial.println();\n  Serial.printf(\"Received :\\t%d\", receiveNb);\n  Serial.println();\n  Serial.printf(\"Sent :\\t%d\", n_sent-error_send);\n  Serial.println();\n  for(int i=0;i<recv_list_len;i++) {\n    Serial.printf(\"%c\",base[recv_list[i]]);\n  }\n  Serial.println();\n}\n"
  },
  {
    "path": "ESP32-Test/t_callbacks.ino",
    "content": "void sendData() {\n  if(n_sent < N_BATCH) {\n    long mytime = micros();\n    int packet_nb = n_sent - error_send;\n    memcpy(txData, &mytime, sizeof(mytime));\n    memcpy(txData+sizeof(mytime), &packet_nb, sizeof(packet_nb));\n    esp_now_send(peer.peer_addr, txData, sizeof(txData[0])*DATA_LEN);\n    n_sent++;\n  }\n}\n\n\nvoid OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {\n  if(status != ESP_OK) {\n    error_send++;\n  }\n}\n\n\nvoid OnDataRecv(const uint8_t *mac, const uint8_t *rxData, int len) {\n  long receiveTime = micros();\n  long sendTime;\n  int packet_nb;\n      \n    if(len>sizeof(sendTime)) {\n      memcpy(&sendTime, rxData, sizeof(sendTime));\n      memcpy(&packet_nb, rxData+sizeof(sendTime), sizeof(packet_nb));\n\n      if(sendTime>batchStart) {\n        fill_histo(receiveTime - sendTime, packet_nb);\n      }\n    } else {\n      error_recv++;\n    }\n}\n"
  },
  {
    "path": "ESP32-Test/z_setup_loop.ino",
    "content": "#define TRY_ESP_ACTION(action, name) if(action == ESP_OK) {Serial.println(\"\\t+ \"+String(name));} else {Serial.println(\"----------Error while \" + String(name) + \" !---------------\");}\n\n\nvoid setup() {\n  Serial.begin(115200);\n\n  WiFi.disconnect();\n  //Set device in STA mode to begin with\n\n  WiFi.mode(WIFI_STA);\n  \n  Serial.println(\"ESPNow/Basic/Master Example\");\n  // This is the mac address of the Master in Station Mode\n  Serial.print(\"STA MAC: \"); Serial.println(WiFi.macAddress());\n\n  TRY_ESP_ACTION( esp_wifi_stop(), \"stop WIFI\");\n  \n  TRY_ESP_ACTION( esp_wifi_deinit(), \"De init\");\n\n  wifi_init_config_t my_config = WIFI_INIT_CONFIG_DEFAULT();\n  my_config.ampdu_tx_enable = 0;\n  \n  TRY_ESP_ACTION( esp_wifi_init(&my_config), \"Disable AMPDU\");\n  \n  TRY_ESP_ACTION( esp_wifi_start(), \"Restart WiFi\");\n\n  TRY_ESP_ACTION( esp_wifi_set_channel(CHANNEL, WIFI_SECOND_CHAN_NONE), \"Set channel\");\n\n  TRY_ESP_ACTION( esp_wifi_internal_set_fix_rate(ESP_IF_WIFI_STA, true, DATARATE), \"Fixed rate set up\");\n\n  TRY_ESP_ACTION( esp_now_init(), \"ESPNow Init\");\n\n  TRY_ESP_ACTION(  esp_now_register_send_cb(OnDataSent), \"Attach send callback\");\n  \n  TRY_ESP_ACTION( esp_now_register_recv_cb(OnDataRecv), \"Attach recv callback\");\n  \n  memset(&peer, 0, sizeof(peer));\n\n  for (int ii = 0; ii < 6; ++ii ) {\n    peer.peer_addr[ii] = (uint8_t) dest_mac[ii];\n  }\n  \n  peer.channel = CHANNEL; // pick a channel\n  peer.encrypt = 0; // no encryption\n      \n  TRY_ESP_ACTION( esp_now_add_peer(&peer), \"Add peer\");\n\n  n_sent = 0;\n  init_data();\n  blinker.attach(0.001, sendData);\n}\n\nvoid loop() {\n  if(n_sent >= N_BATCH) {\n    delay(2000);\n    \n    print_histo();\n    init_histo();\n    \n    n_sent=0;\n    batchStart = micros();\n    \n  } else {\n    yield();\n  }\n}\n"
  },
  {
    "path": "ESP8266-Test/ESP8266-Test.ino",
    "content": "/*\n   19/02/2019 Mac adress modified : Dell laptop\n\n  Master/Server:\n    Sends a 100Byte ESPNOW data block, and awaits a response\n    SLAVE ADDRESS[84:F3:EB:B3:66:CC]\n    SELF=84:F3:EB:73:55:0D\n\n    \n*/\n\n\n#include <ESP8266WiFi.h>\nextern \"C\" {\n#include <espnow.h>\n}\n\n#include <Ticker.h>  //Ticker Library\n\nTicker blinker;\n\n#define WIFI_CHANNEL 1\n\n//byte selfmac[6] = {0xf8, 0x1a, 0x67, 0xb7, 0xeb, 0x0b};\nbyte selfmac[6] = {0x84, 0xF3, 0xEB, 0x73, 0x55, 0x0D};\n\n#define NB_TRIES 1000\n\n#define HISTO_INF 0\n#define HISTO_SUP 10000\n#define HISTO_N_STEP 10\n\nint histogram[HISTO_N_STEP];\nint histogram_higher;\nint histogram_lower;\nint error_nb;\nint receiveNb;\ndouble avg;\n\nlong batchStart =0;\n\nbool sendNew = true;\n\n//MAC ADDRESS OF THE DEVICE YOU ARE SENDING TO\n//byte remoteDevice[6] = {0x84, 0xF3, 0xEB, 0xB3, 0x66, 0xCC};\n//byte remoteDevice[6] = {0x84, 0xF3, 0xEB, 0x73, 0x55, 0x0D};\n//byte remoteDevice[6] = {0x00, 0x21, 0x6A, 0xAA, 0xC9, 0x8C};\n///byte remoteDevice[6] = {0xf8, 0x1a, 0x67, 0xb7, 0xeb, 0x0b}; //computer\n//byte remoteDevice[6] = {0x84, 0xF3, 0xEB, 0x73, 0x55, 0x1E}; //Deuxieme ESP8266\nbyte remoteDevice[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};\n\nconst byte dataLength = 250;\nbyte txData[dataLength];\nunsigned long n_sent;\nint error;\n\nvoid init_histo() {\n  for(int i=0;i<HISTO_N_STEP;i++) {\n    histogram[i] = 0;\n  }\n  histogram_higher = 0;\n  histogram_lower = 0;\n  error_nb=0;\n  receiveNb=0;\n  avg=0;\n}\n\nint fill_histo(long value) {\n  int index = (value-HISTO_INF) * HISTO_N_STEP / (HISTO_SUP - HISTO_INF);\n  if(index >= HISTO_N_STEP) {\n    histogram_higher++;\n  } else if(index < 0) {\n    histogram_lower++;\n  } else {\n    histogram[index]++;\n  }\n\n  receiveNb++;\n  avg += value;\n}\n\nvoid print_histo() {\n  Serial.printf(\"Bounds\\t%d\\tµs\\t%d\\tµs\", HISTO_INF, HISTO_SUP);\n  Serial.println();\n  Serial.printf(\"Nb out of bounds :\");\n  Serial.println();\n  Serial.printf(\"Higher :\\t%d\\tLower :\\t%d\", histogram_higher, histogram_lower);\n  Serial.println();\n  Serial.printf(\"Histo :\");\n  Serial.println();\n  for(int i=0;i<HISTO_N_STEP;i++) {\n    Serial.printf(\"%d\\t\", histogram[i]);\n  }\n  Serial.println();\n  Serial.printf(\"Average :\\t%f\\t\", receiveNb != 0 ? avg/receiveNb : -1);\n  Serial.println();\n  Serial.printf(\"Received :\\t%d\", receiveNb);\n  Serial.println();\n  Serial.printf(\"Errors :\\t%d\", error_nb);\n  Serial.println();\n}\n\nvoid send_test() {\n  \n  if(n_sent < NB_TRIES) {\n    long mytime = micros();\n    memcpy(txData, &mytime, sizeof(mytime));\n    esp_now_send(remoteDevice, txData, dataLength);\n    n_sent++;\n  } else if (Serial) {\n    print_histo();\n    Serial.println();\n    Serial.println(\"--------------------------\");\n    Serial.println();\n    \n    n_sent=0;\n\n    \n    Serial.println();\n    Serial.println(\"------New test :----------\");\n    Serial.println();\n    init_histo();\n    batchStart = micros();\n  }\n}\n\nvoid setup()\n{\n  for (int i = 0; i < dataLength; i++)\n  {\n    txData[i] = 0x12;\n  }\n\n  wifi_set_macaddr(STATION_IF,selfmac);\n\n\n  \n  pinMode(2, OUTPUT); //TX\n  pinMode(0, OUTPUT); //RX\n  Serial.begin(115200);\n  while(!Serial) {delay(1);}\n  Serial.print(\"\\r\\n\\r\\nDevice MAC: \");\n  WiFi.mode(WIFI_STA);\n  WiFi.begin();\n  Serial.println(WiFi.macAddress());\n  Serial.println(\"\\r\\nESP_Now Dual Mode Transmitter + Receiver [MASTER].\\r\\n\");\n  esp_now_init();\n  delay(10);\n  esp_now_set_self_role(ESP_NOW_ROLE_CONTROLLER);\n  //esp_now_add_peer(remoteDevice, ESP_NOW_ROLE_CONTROLLER, WIFI_CHANNEL, NULL, 0);\n  esp_now_add_peer(NULL, ESP_NOW_ROLE_CONTROLLER, WIFI_CHANNEL, NULL, 0);\n\n  error = esp_now_register_recv_cb([](uint8_t *mac, uint8_t *data, uint8_t len)\n  {\n    long receiveTime = micros();\n    long sendTime;\n    \n    if(len>sizeof(sendTime)) {\n      memcpy(&sendTime, data, sizeof(sendTime));\n\n      if(sendTime>batchStart) {\n        fill_histo(receiveTime - sendTime);\n      }\n    } else {\n      error_nb++;\n    }\n    sendNew = true;\n    \n  });\n\n    esp_now_register_send_cb([](uint8_t* mac, uint8_t sendStatus) {\n    sendNew = sendStatus != 0;\n  });\n  \n  Serial.println(error);// if ==0 is OK\n\n  n_sent = 0;\n  blinker.attach(0.01, send_test);\n}\n\nvoid loop()\n{\n  yield();\n}\n"
  },
  {
    "path": "ESP8266-Test/serial_logger.py",
    "content": "import serial\nimport time\nimport csv\nimport sys\n\nassert len(sys.argv)==3\n\n\nser = serial.Serial(sys.argv[1], 115200)\nser.flushInput()\n\nprint \"Serial opened : \" + str(sys.argv[1])\n\nwhile True:\n\ttry:\n\t\tser_bytes = ser.readline()\n\t\t#print(ser_bytes)\n\t\twith open(sys.argv[2],\"a\") as f:\n\t\t\tf.write(ser_bytes)\n\texcept:\n\t\tprint(\"Keyboard Interrupt\")\n\t\tbreak\n"
  },
  {
    "path": "ESP8266_Echo/ESP8266_Echo.ino",
    "content": "/*\n   19/02/2019 Mac adress modified : Dell laptop\n\n  Master/Server:\n    Sends a 100Byte ESPNOW data block, and awaits a response\n    SLAVE ADDRESS[84:F3:EB:B3:66:CC]\n    SELF=84:F3:EB:73:55:0D\n\n    \n*/\n\n\n#include <ESP8266WiFi.h>\nextern \"C\" {\n#include <espnow.h>\n}\n\n#include <Ticker.h>  //Ticker Library\n\nTicker blinker;\n\n#define WIFI_CHANNEL 1\n\n//byte selfmac[6] = {0xf8, 0x1a, 0x67, 0xb7, 0xeb, 0x0b};\nbyte selfmac[6] = {0x84, 0xF3, 0xEB, 0x73, 0x55, 0x1E};\n\n//MAC ADDRESS OF THE DEVICE YOU ARE SENDING TO\n//byte remoteDevice[6] = {0x84, 0xF3, 0xEB, 0xB3, 0x66, 0xCC};\n//byte remoteDevice[6] = {0x84, 0xF3, 0xEB, 0x73, 0x55, 0x0D};\n//byte remoteDevice[6] = {0x00, 0x21, 0x6A, 0xAA, 0xC9, 0x8C};\n///byte remoteDevice[6] = {0x84, 0xF3, 0xEB, 0x73, 0x55, 0x0D};\n//byte remoteDevice[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; //broadcast\nbyte remoteDevice[6] {0xB4,0xE6,0x2D,0xB5,0x9F,0x85}; //ESP32\n\nconst byte dataLength = 250;\nbyte txData[dataLength];\nint error;\n\nvoid send_echo(byte *rxpacket) {\n    memcpy(txData, rxpacket, 8);\n    esp_now_send(remoteDevice, txData, dataLength);\n}\n\nvoid setup()\n{\n  for (int i = 0; i < dataLength; i++)\n  {\n    txData[i] = 0x13;\n  }\n\n  wifi_set_macaddr(STATION_IF,selfmac);\n\n  Serial.begin(115200);\n  while(!Serial) {delay(1);}\n  Serial.print(\"\\r\\n\\r\\nDevice MAC: \");\n  WiFi.mode(WIFI_STA);\n  WiFi.begin();\n  Serial.println(WiFi.macAddress());\n  Serial.println(\"\\r\\nESP_Now Dual Mode Transmitter + Receiver [MASTER].\\r\\n\");\n  esp_now_init();\n  delay(10);\n  esp_now_set_self_role(ESP_NOW_ROLE_CONTROLLER);\n  //esp_now_add_peer(remoteDevice, ESP_NOW_ROLE_CONTROLLER, WIFI_CHANNEL, NULL, 0);\n  esp_now_add_peer(NULL, ESP_NOW_ROLE_CONTROLLER, WIFI_CHANNEL, NULL, 0);\n\n\n  error = esp_now_register_recv_cb([](uint8_t *mac, uint8_t *data, uint8_t len)\n  {\n    if(len>8) {\n      send_echo(data);\n    }\n  });\n  \n  Serial.println(error);// if ==0 is OK\n}\n\nvoid loop()\n{\n  yield();\n}\n"
  },
  {
    "path": "ESPNOW_lib/Makefile",
    "content": "\nCC = g++\nCFLAGS  = -g -Wall -std=c++11\nINCLUDES = -I src/Includes/\n\ndefault: all\n\n%.o: src/%.cpp\n\tmkdir -p bin\n\t$(CC) $(CFLAGS) $(INCLUDES) -o bin/$@ -c $^\n\napp: main.o ESPNOW_manager.o ESPNOW_types.o\n\t$(CC) $(CFLAGS) -o bin/exec $(addprefix bin/,$^) -pthread\n\n\nall: clear clean app\n\nclean: \n\t$(RM) bin/*\n\nclear:\n\tclear\n"
  },
  {
    "path": "ESPNOW_lib/README.MD",
    "content": "# Before using this code\nDo not forget to turn on monitor mode and choose the right channel on your wireless interface card.\n\nHere is a exmaple on how to do it : \n```\nsudo ifconfig wlp5s0 down\nsudo iwconfig wlp5s0 mode monitor\nsudo ifconfig wlp5s0 up\nsudo iwconfig wlp5s0 channel 1 \n```\n\n"
  },
  {
    "path": "ESPNOW_lib/src/ESPNOW_manager.cpp",
    "content": "\n#include <string.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <sys/types.h>\n#include <stdint.h>\n#include <pthread.h>\n#include <unistd.h>\n\n#include <sys/socket.h>\n#include <sys/ioctl.h>\n#include <linux/if_arp.h>\n#include <arpa/inet.h>\n#include <assert.h>\n\n#include \"ESPNOW_manager.h\"\n\n#include \"ESPNOW_types.h\"\n\n#define MAC_2_MSBytes(MAC)  MAC == NULL ? 0 : (MAC[0] << 8) | MAC[1]\n#define MAC_4_LSBytes(MAC)  MAC == NULL ? 0 : (((((MAC[2] << 8) | MAC[3]) << 8) | MAC[4]) << 8) | MAC[5]\n\nvoid ESPNOW_manager::set_interface(char* interface) {\n\tthis->interface = (char*) malloc(strlen(interface)*sizeof(char));\t\n\tstrcpy(this->interface, interface);\n}\n\nvoid ESPNOW_manager::set_recv_callback(void (*callback)(uint8_t src_mac[6], uint8_t *data, int len)) {\n\trecv_thread_params.callback = callback;\n}\n\nvoid ESPNOW_manager::unset_filter() {\n\tif(this->bpf.filter != NULL) {\n\t\tfree(this->bpf.filter);\n\t\tthis->bpf.filter = NULL;\n\t}\n\tthis->bpf.len = 0;\n}\n\nvoid ESPNOW_manager::set_filter(uint8_t *src_mac, uint8_t *dst_mac) {\n\t//sudo tcpdump -i wlp5s0 'type 0 subtype 0xd0 and wlan[24:4]=0x7f18fe34 and wlan[32]=221 and wlan[33:4]&0xffffff = 0x18fe34 and wlan[37]=0x4 and wlan dst 11:22:33:44:55:66 and wlan src 77:88:99:aa:bb:cc' -dd\n\tunset_filter();\n\n\tthis->bpf.len = 53;\n\n\tuint32_t MSB_dst = MAC_2_MSBytes(dst_mac);\n\tuint32_t LSB_dst = MAC_4_LSBytes(dst_mac);\n\n\tuint32_t MSB_src = MAC_2_MSBytes(src_mac);\n\tuint32_t LSB_src = MAC_4_LSBytes(src_mac);\n\n\tuint8_t jeq_dst = dst_mac == NULL ? 0x30 : 0x15; //0x30 jump if >=. 0x15 jump if ==.\n\tuint8_t jeq_src = src_mac == NULL ? 0x30 : 0x15;\n\n\tstruct sock_filter temp_code[this->bpf.len] = {\n\t\t\t{ 0x30, 0, 0, 0x00000003 },\n\t\t\t{ 0x64, 0, 0, 0x00000008 },\n\t\t\t{ 0x7, 0, 0, 0x00000000 },\n\t\t\t{ 0x30, 0, 0, 0x00000002 },\n\t\t\t{ 0x4c, 0, 0, 0x00000000 },\n\t\t\t{ 0x2, 0, 0, 0x00000000 },\n\t\t\t{ 0x7, 0, 0, 0x00000000 },\n\t\t\t{ 0x50, 0, 0, 0x00000000 },\n\t\t\t{ 0x54, 0, 0, 0x000000fc },\n\t\t\t{ 0x15, 0, 42, 0x000000d0 },\n\t\t\t{ 0x40, 0, 0, 0x00000018 },\n\t\t\t{ 0x15, 0, 40, 0x7f18fe34 },\n\t\t\t{ 0x50, 0, 0, 0x00000020 },\n\t\t\t{ 0x15, 0, 38, 0x000000dd },\n\t\t\t{ 0x40, 0, 0, 0x00000021 },\n\t\t\t{ 0x54, 0, 0, 0x00ffffff },\n\t\t\t{ 0x15, 0, 35, 0x0018fe34 },\n\t\t\t{ 0x50, 0, 0, 0x00000025 },\n\t\t\t{ 0x15, 0, 33, 0x00000004 },\n\t\t\t{ 0x50, 0, 0, 0x00000000 },\n\t\t\t{ 0x45, 31, 0, 0x00000004 },\n\t\t\t{ 0x45, 0, 21, 0x00000008 },\n\t\t\t{ 0x50, 0, 0, 0x00000001 },\n\t\t\t{ 0x45, 0, 4, 0x00000001 },\n\t\t\t{ 0x40, 0, 0, 0x00000012 },\n\t\t\t{ jeq_dst, 0, 26, LSB_dst },\n\t\t\t{ 0x48, 0, 0, 0x00000010 },\n\t\t\t{ jeq_dst, 4, 24, MSB_dst },\n\t\t\t{ 0x40, 0, 0, 0x00000006 },\n\t\t\t{ jeq_dst, 0, 22, LSB_dst },\n\t\t\t{ 0x48, 0, 0, 0x00000004 },\n\t\t\t{ jeq_dst, 0, 20, MSB_dst },\n\t\t\t{ 0x50, 0, 0, 0x00000001 },\n\t\t\t{ 0x45, 0, 13, 0x00000002 },\n\t\t\t{ 0x45, 0, 4, 0x00000001 },\n\t\t\t{ 0x40, 0, 0, 0x0000001a },\n\t\t\t{ jeq_src, 0, 15, LSB_src },\n\t\t\t{ 0x48, 0, 0, 0x00000018 },\n\t\t\t{ jeq_src, 12, 13, MSB_src },\n\t\t\t{ 0x40, 0, 0, 0x00000012 },\n\t\t\t{ jeq_src, 0, 11, LSB_src },\n\t\t\t{ 0x48, 0, 0, 0x00000010 },\n\t\t\t{ jeq_src, 8, 9, MSB_src },\n\t\t\t{ 0x40, 0, 0, 0x00000006 },\n\t\t\t{ jeq_dst, 0, 7, LSB_dst },\n\t\t\t{ 0x48, 0, 0, 0x00000004 },\n\t\t\t{ jeq_dst, 0, 5, MSB_dst },\n\t\t\t{ 0x40, 0, 0, 0x0000000c },\n\t\t\t{ jeq_src, 0, 3, LSB_src },\n\t\t\t{ 0x48, 0, 0, 0x0000000a },\n\t\t\t{ jeq_src, 0, 1, MSB_src },\n\t\t\t{ 0x6, 0, 0, 0x00040000 },\n\t\t\t{ 0x6, 0, 0, 0x00000000 }\n\t\t\t\t\t\t};\n\n\tthis->bpf.filter = (sock_filter*) malloc(sizeof(sock_filter)*this->bpf.len);\n\tmemcpy(this->bpf.filter, temp_code, sizeof(struct sock_filter) * this->bpf.len);\n}\n\n\nvoid ESPNOW_manager::start() {\n\tstruct sockaddr_ll s_dest_addr;\n    struct ifreq ifr;\n\t\n    int fd, \t\t\t//file descriptor\n\t\tioctl_errno,\t//ioctl errno\n\t\tbind_errno,\t\t//bind errno\n\t\tfilter_errno,\t//attach filter errno\n\t\tpriority_errno;\t//Set priority errno\n\n\tbzero(&s_dest_addr, sizeof(s_dest_addr));\n    bzero(&ifr, sizeof(ifr));\n\t\n\t\n    fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));\n    assert(fd != -1);\n\n    strncpy((char *)ifr.ifr_name, this->interface, IFNAMSIZ); //interface\n\n    ioctl_errno = ioctl(fd, SIOCGIFINDEX, &ifr);\n    assert(ioctl_errno >= 0);\t//abort if error\n\n    s_dest_addr.sll_family = PF_PACKET;\n    s_dest_addr.sll_protocol = htons(ETH_P_ALL);\n    s_dest_addr.sll_ifindex = ifr.ifr_ifindex;\n    \n    bind_errno = bind(fd, (struct sockaddr *)&s_dest_addr, sizeof(s_dest_addr));\n    assert(bind_errno >= 0);\t//abort if error\n\t\n\t\n\tif(bpf.len > 0) {\n\t\tfilter_errno = setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &(this->bpf), sizeof(bpf));\n\t\tassert(filter_errno >= 0);\n\t}\n\n\n\tpriority_errno = setsockopt(fd, SOL_SOCKET, SO_PRIORITY, &(this->socket_priority), sizeof(this->socket_priority));\n\tassert(priority_errno ==0);\n\t\n\tthis->sock_fd = fd;\n\n\tthis->recv_thread_params.sock_fd = this->sock_fd;\n\n\tpthread_create (&recv_thd_id, NULL, &(ESPNOW_manager::sock_recv_thread), &recv_thread_params);\n    \n}\n\nvoid ESPNOW_manager::stop() {\n\tif(recv_thd_id) {\n\t\tpthread_cancel(recv_thd_id);\n\t}\n\tif (this->sock_fd > 0)\n    {\n        close(this->sock_fd);\n    }\n}\n\nvoid ESPNOW_manager::end() {\n\tstop();\n\n\tif(this->interface != NULL) {\n\t\tfree(this->interface);\n\t\tthis->interface = NULL;\n\t}\n\t\n\tif(this->bpf.filter != NULL) {\n\t\tfree(this->bpf.filter);\n\t\tthis->bpf.filter = NULL;\n\t}\n}\n\nvoid* ESPNOW_manager::sock_recv_thread (void *p_arg)\n{\n\tint raw_bytes_len;\n\tuint8_t raw_bytes[LEN_RAWBYTES_MAX];\n\n\tuint8_t* res_mac;\n\tuint8_t* res_payload;\n\tint res_len;\n\n\tstruct thread_args params = * ((struct thread_args *)p_arg);\n\n\tif(params.callback == NULL) {\n\t\tprintf (\"No callback for receive, receive thread exited\\n\");\n    \treturn EXIT_SUCCESS;\n\t};\n\n\twhile(1)\n    {\t\n        raw_bytes_len = recvfrom (params.sock_fd, raw_bytes, LEN_RAWBYTES_MAX, MSG_TRUNC, NULL, 0);\n\n        if( -1 == raw_bytes_len )\n        {\n            perror (\"Socket receive failed\");\n            break;\n        }\n        else if( raw_bytes_len < 0 )\n        {\n            perror (\"Socket receive, error \");\n        }\n        else\n        {\n        \tres_mac = ESPNOW_packet::get_src_mac(raw_bytes,raw_bytes_len);\n        \tres_payload = ESPNOW_packet::get_payload(raw_bytes, raw_bytes_len);\n        \tres_len = ESPNOW_packet::get_payload_len(raw_bytes, raw_bytes_len);\n        \tif(res_mac != NULL && res_payload != NULL && res_len > 0) {\n        \t\tparams.callback(res_mac, res_payload, res_len);\n        \t}\n        }\n    }\n\n    printf (\"Receive thread exited \\n\");\n    return EXIT_SUCCESS;\n}\n\n\n/*\nint ESPNOW_manager::send(ESPNOW_packet p) {\n\tuint8_t raw_bytes[LEN_RAWBYTES_MAX];\n\tint len = p.toBytes(raw_bytes, LEN_RAWBYTES_MAX);\n\n\treturn sendto(this->sock_fd, raw_bytes, len, 0, NULL, 0);\n}\n*/\n\n\nint ESPNOW_manager::send(uint8_t *payload, int len) {\n\tuint8_t raw_bytes[LEN_RAWBYTES_MAX];\n\n\t//Not the most fastest way to do this : \n\t//\tcopy the payload in the packet array and then copy it back into the buffer...\n\tthis->mypacket.wlan.actionframe.content.set_length(len); \n\tmemcpy(this->mypacket.wlan.actionframe.content.payload, payload, len);\n\n\tint raw_len = mypacket.toBytes(raw_bytes, LEN_RAWBYTES_MAX);\n\n\treturn sendto(this->sock_fd, raw_bytes, raw_len, 0, NULL, 0);\n}\n\nint ESPNOW_manager::send() {\n\tuint8_t raw_bytes[LEN_RAWBYTES_MAX];\n\n\tint raw_len = mypacket.toBytes(raw_bytes, LEN_RAWBYTES_MAX);\n\n\treturn sendto(this->sock_fd, raw_bytes, raw_len, 0, NULL, 0);\n}\n\n"
  },
  {
    "path": "ESPNOW_lib/src/ESPNOW_types.cpp",
    "content": "#include \"ESPNOW_types.h\"\n\n#include <stdint.h>\n#include <string.h>\n#include <sys/types.h>\n#include <assert.h>\n\nvoid ESPNOW_packet::set_channel(uint16_t channel_freq) {\nthis->radiotap.channel_freq = channel_freq;\n}\n\nvoid ESPNOW_packet::set_datarate(uint8_t datarate) {\n\tthis->radiotap.datarate = datarate;\n}\n\nvoid ESPNOW_packet::set_src_mac(uint8_t my_mac[6]) {\n\tmemcpy(this->wlan.sa, my_mac, sizeof(uint8_t)*6);\n}\n\nvoid ESPNOW_packet::set_dst_mac(uint8_t dst_mac[6]) {\n\tmemcpy(this->wlan.da, dst_mac, sizeof(uint8_t)*6);\n\tmemcpy(this->wlan.bssid, dst_mac, sizeof(uint8_t)*6);\n}\n\nint ESPNOW_packet::toBytes(uint8_t *bytes, int max_len) {\t\n\tint correct_len = sizeof(ESPNOW_packet) + this->wlan.actionframe.content.length - 0xff;\n\t\n\tassert(correct_len <= max_len); \n\n\tmemcpy(bytes, this, correct_len);\t\n\t\n\tmemcpy(bytes + correct_len - sizeof(this->wlan.fcs), &(this->wlan.fcs), sizeof(this->wlan.fcs));\n\n\treturn correct_len;\n}\n\nint ESPNOW_packet::get_radiotap_len(uint8_t *raw_bytes, int len) {\n\tif(len < 4) return -1;\n\treturn (int)raw_bytes[2] + ((int)raw_bytes[3] << 8);\n}\n\nuint8_t* ESPNOW_packet::get_src_mac(uint8_t *raw_bytes, int len) {\n\tint radiotap_len = get_radiotap_len(raw_bytes, len);\n\n\tif(len < radiotap_len + 10 + 6) return NULL;\n\n\treturn raw_bytes + radiotap_len + 10;\n}\n\nint ESPNOW_packet::get_payload_len(uint8_t *raw_bytes, int len) {\n\tint radiotap_len = get_radiotap_len(raw_bytes, len);\n\t\n\tif(len < radiotap_len + WLAN_LEN + ACTIONFRAME_HEADER_LEN + 1) return -1;\n\n\treturn raw_bytes[radiotap_len + WLAN_LEN + ACTIONFRAME_HEADER_LEN + 1] - 5;\n}\n\nuint8_t* ESPNOW_packet::get_payload(uint8_t *raw_bytes, int len) {\n\tint radiotap_len = get_radiotap_len(raw_bytes, len);\n\n\tif(len < radiotap_len + WLAN_LEN + ACTIONFRAME_HEADER_LEN + VENDORSPECIFIC_CONTENT_LEN) return NULL;\n\t\n\treturn raw_bytes + radiotap_len + WLAN_LEN + ACTIONFRAME_HEADER_LEN + VENDORSPECIFIC_CONTENT_LEN;\n}\n"
  },
  {
    "path": "ESPNOW_lib/src/Includes/ESPNOW_manager.h",
    "content": "#ifndef ESPNOW_manager_H\n#define ESPNOW_manager_H\n\n#include <stdint.h>\n#include <linux/filter.h>\n#include <string.h>\n#include <sys/types.h>\n#include <stdint.h>\n#include <pthread.h>\n\n#include \"ESPNOW_types.h\"\n\n\n#define LEN_RAWBYTES_MAX 512\n\nstruct thread_args {\n\tint sock_fd;\n\tvoid (*callback)(uint8_t src_mac[6], uint8_t *data, int len);\n};\n\nclass ESPNOW_manager {\n\tpublic:\n\t\tESPNOW_manager() {\n\t\t\tdefault_values();\n\t\t}\n\n\t\tESPNOW_manager(char* interface) {\n\t\t\tdefault_values();\n\t\t\tset_interface(interface);\n\t\t}\n\n\t\tESPNOW_manager(char* interface, uint8_t datarate, uint16_t channel_freq, uint8_t src_mac[6], uint8_t dst_mac[6], bool filterOn) {\n\t\t\tdefault_values();\n\t\t\tset_interface(interface);\n\t\t\tset_channel(channel_freq);\n\t\t\tset_datarate(datarate);\n\t\t\tset_src_mac(src_mac);\n\t\t\tset_dst_mac(dst_mac);\n\t\t\t\n\t\t\tif(filterOn) {\n\t\t\t\tset_filter(dst_mac, src_mac);\n\t\t\t} else {\n\t\t\t\tset_filter(NULL, NULL);\n\t\t\t}\n\t\t\t\n\t\t}\n\n\t\tvoid unset_filter();\n\t\tvoid set_filter(uint8_t *src_mac, uint8_t *dst_mac);\n\t\tvoid set_interface(char* interface);\n\t\tvoid set_recv_callback(void (*callback)(uint8_t src_mac[6], uint8_t *data, int len));\n\t\t\n\t\tvoid start();\n\t\tvoid stop();\n\t\tvoid end();\n\t\t\n\t\t//int send(ESPNOW_packet p);\n\t\tint send(uint8_t *payload, int len);\n\t\tint send();\n\t\t\n\t\tvoid set_channel(uint16_t channel_freq) { mypacket.set_channel(channel_freq); }\n\t\tvoid set_datarate(uint8_t datarate) { mypacket.set_datarate(datarate); }\n\t\tvoid set_src_mac(uint8_t src_mac[6]) { mypacket.set_src_mac(src_mac); }\n\t\tvoid set_dst_mac(uint8_t dst_mac[6]) { mypacket.set_dst_mac(dst_mac); }\n\t\n\n\t\tESPNOW_packet mypacket;\n\tprivate:\n\t\tint sock_fd;\n\t\tstruct sock_fprog bpf;\n\t\tint socket_priority;\n\t\tchar* interface;\n\n\t\t\n\n\t\tpthread_t recv_thd_id;\n\t\tstruct thread_args recv_thread_params;\n\t\tstatic void* sock_recv_thread (void *p_arg);\n\n\t\tvoid default_values() {\n\t\t\tbpf.len = 0;\n\t\t\tsocket_priority = 7; //Priority\n\t\t\trecv_thread_params.callback = NULL;\n\t\t}\n\n};\n\n\n\n#endif\n"
  },
  {
    "path": "ESPNOW_lib/src/Includes/ESPNOW_types.h",
    "content": "#ifndef ESPNOW_TYPES_H\n#define ESPNOW_TYPES_H\n\n#include <string.h>\n#include <stdint.h>\n\n#define DATARATE_1Mbps 0x02\n#define DATARATE_2Mbps 0x04\n#define DATARATE_6Mbps 0x0c\n#define DATARATE_9Mbps 0x12\n#define DATARATE_12Mbps 0x18\n#define DATARATE_18Mbps 0x24\n#define DATARATE_24Mbps 0x30\n#define DATARATE_36Mbps 0x48\n#define DATARATE_48Mbps 0x60\n#define DATARATE_54Mbps 0x6c\n\n#define CHANNEL_freq_1 2412\n#define CHANNEL_freq_2 2417\n#define CHANNEL_freq_3 2422\n#define CHANNEL_freq_4 2427\n#define CHANNEL_freq_5 2432\n#define CHANNEL_freq_6 2437\n#define CHANNEL_freq_7 2442\n#define CHANNEL_freq_8 2447\n#define CHANNEL_freq_9 2452\n#define CHANNEL_freq_10 2457\n#define CHANNEL_freq_11 2462\n#define CHANNEL_freq_12 2467\n#define CHANNEL_freq_13 2472\n\n#define WLAN_LEN 24\n#define ACTIONFRAME_HEADER_LEN 8\n#define VENDORSPECIFIC_CONTENT_LEN 7\n\nstruct IEEE80211_radiotap {\n\tuint8_t version;\n    uint8_t pad;\n    uint16_t length;\n    uint32_t present;\n    uint8_t flags;\n    uint8_t datarate;\n    uint16_t channel_freq;\n    uint16_t channel_flags_quarter;\n\n\t//Default values for ESPNOW\n\tIEEE80211_radiotap() {\n\t\tthis->version = 0;\n\t\tthis->pad = 0;\n\t\tthis->length = sizeof(IEEE80211_radiotap);\n\t\tthis->present = 0x0000000e;\n\t\tthis->flags = 0x10;\n\t\tthis->datarate = DATARATE_6Mbps;\n\t\tthis->channel_freq = CHANNEL_freq_1;\n\t\tthis->channel_flags_quarter = 0x00c0;\n\t}\n} __attribute__((__packed__));\n\n\nstruct IEEE80211_vendorspecific {\n\tuint8_t elementID;\n\tuint8_t length;\n\tuint8_t\tOUI[3];\n\tuint8_t type;\n\tuint8_t version;\n\tuint8_t payload[250];\n\n\t//Default values for ESPNOW\n\tIEEE80211_vendorspecific() {\n\t\tthis->elementID = 0xdd;\n\t\tthis->OUI[0] = 0x18;\n\t\tthis->OUI[1] = 0xfe;\n\t\tthis->OUI[2] = 0x34;\n\t\tthis->type = 0x04;\n\t\tthis->version = 0x01;\n\t}\n\n\tvoid set_length(int length) {this->length = length + 5;}\n} __attribute__((__packed__));\n\n\nstruct IEEE80211_actionframe {\n\tuint8_t category_code;\n    uint8_t OUI[3];\n\tuint8_t unknown_bytes[4];\n\tstruct IEEE80211_vendorspecific content;\n\n\t//Default values for ESPNOW\n\tIEEE80211_actionframe() {\n\t\tthis->category_code = 0x7f;\n\t\tthis->OUI[0] = 0x18;\n\t\tthis->OUI[1] = 0xfe;\n\t\tthis->OUI[2] = 0x34;\n\t\tbzero(this->unknown_bytes, 4);\n\t}\n} __attribute__((__packed__));\n\n\nstruct IEEE80211_wlan {\n\tuint8_t type;\n    uint8_t flags;\n    uint16_t duration;\n    uint8_t da[6];\n    uint8_t sa[6];\n    uint8_t bssid[6];\n    uint16_t seq;\n\tstruct IEEE80211_actionframe actionframe;\n    uint32_t fcs;\n\n\t//Default values for ESPNOW\n\tIEEE80211_wlan() {\n\t\tthis->type = 0xd0;\n\t\tthis->flags = 0x00;\n\t\tthis->duration = 0x0000; //Will be recalculated by the hardware...\n\t\tthis->seq = 0x0280;\n\t\tthis->fcs = 0x00000000;\t//Will be recalculated by the hardware...\n\t}\n} __attribute__((__packed__));\n\n\ntypedef struct {\n\tstruct IEEE80211_radiotap radiotap;\n\tstruct IEEE80211_wlan wlan;\n\n\tvoid set_channel(uint16_t channel_freq);\n\tvoid set_datarate(uint8_t datarate);\n\tvoid set_src_mac(uint8_t my_mac[6]);\n\tvoid set_dst_mac(uint8_t dst_mac[6]);\n\t\n\tint toBytes(uint8_t *bytes, int max_len);\n\n\tstatic int get_radiotap_len(uint8_t *raw_bytes, int len);\n\tstatic uint8_t* get_src_mac(uint8_t *raw_bytes, int len);\n\tstatic int get_payload_len(uint8_t *raw_bytes, int len);\n\tstatic uint8_t* get_payload(uint8_t *raw_bytes, int len);\n\n} __attribute__((__packed__)) ESPNOW_packet;\n\n#endif\n"
  },
  {
    "path": "ESPNOW_lib/src/main.cpp",
    "content": "/*\nEtienne Arlaud\n*/\n\n#include <stdint.h>\n#include <stdio.h>\n\n#include <assert.h>\n#include <unistd.h>\n#include <sys/time.h>\n\n#include <thread>\n\n#include \"ESPNOW_manager.h\"\n#include \"ESPNOW_types.h\"\n\nusing namespace std;\n\nstatic uint8_t my_mac[6] = {0xF8, 0x1A, 0x67, 0xb7, 0xEB, 0x0B};\nstatic uint8_t dest_mac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};\nstatic uint8_t ESP_mac[6] = {0xB4,0xE6,0x2D,0xB5,0x9F,0x85};\n\nESPNOW_manager *handler;\n\nuint8_t payload[127];\n\nvoid callback(uint8_t src_mac[6], uint8_t *data, int len) {\n\thandler->mypacket.wlan.actionframe.content.length = 127 + 5;\n\tmemcpy(handler->mypacket.wlan.actionframe.content.payload, data, 6);\n\t//handler->set_dst_mac(dest_mac);\n\thandler->send();\n}\n\nint main(int argc, char **argv) {\n\tassert(argc > 1);\n\n\tnice(-20);\n\n\thandler = new ESPNOW_manager(argv[1], DATARATE_24Mbps, CHANNEL_freq_9, my_mac, dest_mac, false);\n\n\thandler->set_filter(ESP_mac, dest_mac);\n\n\thandler->set_recv_callback(&callback);\n\n\thandler->start();\n\n\twhile(1) {\n\t\tstd::this_thread::yield();\n\t}\n\n\thandler->end();\n}\n"
  },
  {
    "path": "LICENSE",
    "content": "BSD 2-Clause License\n\nCopyright (c) 2019, thomasfla\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n* Redistributions of source code must retain the above copyright notice, this\n  list of conditions and the following disclaimer.\n\n* Redistributions in binary form must reproduce the above copyright notice,\n  this list of conditions and the following disclaimer in the documentation\n  and/or other materials provided with the distribution.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\nAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\nFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\nOR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
  },
  {
    "path": "Lab/EspNowPacket/EspNowPacket.c",
    "content": "/*\nFlorenc Caminade\nThomas FLayols\n\nSend ESP-NOW vendor specific action frame example\nhttps://hackaday.io/project/161896\nhttps://github.com/thomasfla/Linux-ESPNOW\n\nAdapted from : \nhttps://stackoverflow.com/questions/10824827/raw-sockets-communication-over-wifi-receiver-not-able-to-receive-packets\n\n1/Find your wifi interface:\n$ iwconfig\n\n2/Setup your interface in monitor mode :\n$ sudo ifconfig wlp5s0 down\n$ sudo iwconfig wlp5s0 mode monitor\n$ sudo ifconfig wlp5s0 up\n\n3/Run this code as root\n*/\n#include <stdint.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <unistd.h>\n#include <sys/socket.h>\n#include <sys/ioctl.h>\n#include <linux/if_arp.h>\n#include <arpa/inet.h>\n#include <assert.h>\n\nint packetSetUp(uint8_t* packet, uint8_t* mac_dest, uint8_t* mac_src, uint8_t* payload, int len );\n\nstatic uint8_t mac_src[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};\nstatic uint8_t mac_dest[6] = {0x84, 0xF3, 0xEB, 0x73, 0x55, 0x0D};\nstatic uint8_t gu8a_dest_mac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};\n\nstatic uint8_t payload[20] = {0};\nstatic int len = 20;\nuint8_t esppacket[400] = {0};\n\n\nint create_raw_socket(char *dev)\n{\n    struct sockaddr_ll s_dest_addr; //code from sender\n    struct ifreq ifr;\n    int fd, ifi, rb;\n\n    bzero(&s_dest_addr, sizeof(s_dest_addr));\n    bzero(&ifr, sizeof(ifr));\n\n    (void)memset(&s_dest_addr, 0, sizeof(s_dest_addr));\n\n    fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));\n    assert(fd != -1); //abort if error\n\n    strncpy((char *)ifr.ifr_name, dev, IFNAMSIZ);\n    ifi = ioctl(fd, SIOCGIFINDEX, &ifr);\n    assert(ifi != -1); //abort if error\n\n    s_dest_addr.sll_family = PF_PACKET;\n    //we don't use a protocol above ethernet layer, just use anything here\n    s_dest_addr.sll_protocol = htons(ETH_P_ALL);\n    s_dest_addr.sll_ifindex = ifr.ifr_ifindex;\n    s_dest_addr.sll_hatype = ARPHRD_ETHER;\n    s_dest_addr.sll_pkttype = PACKET_OTHERHOST; //PACKET_OUTGOING\n    s_dest_addr.sll_halen = ETH_ALEN;\n    //MAC - begin\n    s_dest_addr.sll_addr[0] = gu8a_dest_mac[0];\n    s_dest_addr.sll_addr[1] = gu8a_dest_mac[1];\n    s_dest_addr.sll_addr[2] = gu8a_dest_mac[2];\n    s_dest_addr.sll_addr[3] = gu8a_dest_mac[3];\n    s_dest_addr.sll_addr[4] = gu8a_dest_mac[4];\n    s_dest_addr.sll_addr[5] = gu8a_dest_mac[5];\n    //MAC - end\n    s_dest_addr.sll_addr[6] = 0x00; //not used\n    s_dest_addr.sll_addr[7] = 0x00; //not used\n\n    rb = bind(fd, (struct sockaddr *)&s_dest_addr, sizeof(s_dest_addr));\n    assert(rb != -1); //abort if error\n\n    return fd;\n}\n\nint main(int argc, char **argv)\n{\n    char *dev = argv[1];\n\n    int sock_fd = -1;\n    int32_t s32_res = -1;\n\n    sock_fd = create_raw_socket(dev); /* Creating the raw socket */\n\n    if (-1 == sock_fd)\n    {\n        perror(\"Could not create the socket\");\n        goto LABEL_CLEAN_EXIT;\n    }\n\n    printf(\"Socket created\\n\");\n\n    fflush(stdout);\n\n    sleep(1);\n\n    printf(\"******Sending data using raw socket over  %s \\n\", dev);\n\n    while (1)\n    {\n        int length = packetSetUp(esppacket,mac_dest,mac_src,payload,len);\n\n        s32_res = sendto(sock_fd,esppacket,length,0,NULL,0);\n\n        if (-1 == s32_res)\n        {\n            perror(\"Socket send failed\");\n            goto LABEL_CLEAN_EXIT;\n        }\n        int i = 0;\n        for (i = 0; i < length; i++)\n            printf(\"%x \", esppacket[i]);\n\n        printf(\"\\n\\n\");\n\n        usleep(100);\n    }\n\nLABEL_CLEAN_EXIT:\n    if (sock_fd > 0)\n    {\n        close(sock_fd);\n    }\n\n    printf(\"***** Raw Socket test- end\\n\");\n\n    return EXIT_SUCCESS;\n}\n\n\n\nstruct ieee80211_radiotap_header\n{\n    uint8_t radiotap_version;                //= 0;\n    uint8_t radiotap_pad;                    //= 0;\n    uint16_t radiotap_lenght;                //= 0x00,0x26;\n    uint32_t radiotap_present_1;             //= {0x2f, 0x40, 0x00, 0xa0};\n    uint32_t radiotap_present_2;             //= {0x20, 0x08, 0x00, 0xa0};\n    uint32_t radiotap_present_3;             //= {0x20, 0x08, 0x00, 0x00};\n    uint8_t radiotap_flags;          //= 10;\n    uint8_t radiotap_datarate;               //0x0c\n    uint16_t radiotap_channel_freq;          //0x6c, 0x09\n    uint16_t radiotap_channel_flags_quarter; //0xc0, 0x00\n\n} __attribute__((__packed__));\n\nstruct ieee80211_wlan\n{\n    uint8_t wlan_fc_subtype;          //0xd0\n    uint8_t wlan_fc_order;            //0x00\n    uint16_t wlan_duration;           //0x3a, 0x01\n    uint8_t wlan_da[6];               //0x84, 0xf3, 0xeb, 0x73, 0x55, 0x0d\n    uint8_t wlan_sa[6];               //0xf8, 0x1a, 0x67, 0xb7, 0xeb, 0x0b\n    uint8_t wlan_bssid[6];            //0x84, 0xf3, 0xeb, 0x73, 0x55, 0x0d\n    uint16_t wlan_seq;                //0x70, 0x51\n    uint8_t wlan_fiwed_category_code; //0x7f\n    uint8_t wlan_tag_oui[3];          //0x18,0xfe, 0x34\n\n    uint8_t espheader[11];\n\n    uint8_t payload[261];\n\n    uint32_t wlan_fcs; //0x1c, 0xd5, 0x35, 0xd3\n\n} __attribute__((__packed__));\n\ntypedef struct\n{\n    struct ieee80211_radiotap_header rtap_header;\n    struct ieee80211_wlan mypayload;\n\n} espPacket;\n\n\nint packetSetUp(uint8_t* packet, uint8_t* mac_dest, uint8_t* mac_src, uint8_t* payload, int len )\n{\n    /// packet should be at least x long todo calculate x check///\n    espPacket mypacket; ///to do chage pypacket to packet_header\n\n    mypacket.rtap_header.radiotap_version = 0;\n    mypacket.rtap_header.radiotap_pad = 0;\n    mypacket.rtap_header.radiotap_lenght = sizeof(mypacket.rtap_header);\n    mypacket.rtap_header.radiotap_present_1 = 0xfe;\n\n    mypacket.rtap_header.radiotap_flags = 0x10;\n    mypacket.rtap_header.radiotap_datarate = 0x0c;\n    mypacket.rtap_header.radiotap_channel_freq = 0x096c;\n    mypacket.rtap_header.radiotap_channel_flags_quarter = 0x00c0;\n\n    mypacket.mypayload.wlan_fc_subtype = 0xd0;\n    mypacket.mypayload.wlan_fc_order = 0x00;\n    mypacket.mypayload.wlan_duration = 0x013a;\n\n    memcpy(mypacket.mypayload.wlan_da,mac_dest,6);\n\n    memcpy(mypacket.mypayload.wlan_sa,mac_src,6);\n\n    memcpy(mypacket.mypayload.wlan_bssid,mac_dest,6);\n\n    mypacket.mypayload.wlan_seq = 0x5170;\n    mypacket.mypayload.wlan_fiwed_category_code = 0x7f;\n    mypacket.mypayload.wlan_tag_oui[0] = 0x18;\n    mypacket.mypayload.wlan_tag_oui[1] = 0xfe;\n    mypacket.mypayload.wlan_tag_oui[2] = 0x34;\n\n    mypacket.mypayload.espheader[0] = 0xa2;//element ID\n    mypacket.mypayload.espheader[1] = 0x03;//length of Organization Identifier\n    mypacket.mypayload.espheader[2] = 0x92;\n    mypacket.mypayload.espheader[3] = 0xb0;\n    mypacket.mypayload.espheader[4] = 0xdd;\n    mypacket.mypayload.espheader[5] = 0xff;\n    mypacket.mypayload.espheader[6] = 0x18;//Organization ID\n    mypacket.mypayload.espheader[7] = 0xfe;//Organization ID\n    mypacket.mypayload.espheader[8] = 0x34;//Organization ID\n    mypacket.mypayload.espheader[9] = 0x04;//type (should be 4)\n    mypacket.mypayload.espheader[10] = 0x1;//version field\n\n    memcpy(packet,&mypacket,sizeof(mypacket));\n    memcpy(packet + sizeof(mypacket),payload,len);\n\n    mypacket.mypayload.wlan_fcs = 0x00000000;\n\n    printf(\"%lu\\n\", sizeof(mypacket.rtap_header));\n\n    return sizeof(mypacket)+len;\n}"
  },
  {
    "path": "Lab/EspNowPacket/Makefile",
    "content": "test:\n\tmkdir -p bin\n\tgcc EspNowPacket.c -Wall  -o bin/main\n\nclean:\n\trm -r bin\n"
  },
  {
    "path": "README.md",
    "content": "# Linux-ESPNOW\nAn attempt at implementing a direct link between a linux station and an ESP module using ESPNOW protocol for real time robot control\n\nProject description here: https://hackaday.io/project/161896\n"
  },
  {
    "path": "wifiRawEcho/Includes/ESPNOW_packet.h",
    "content": "#ifndef ESPNOW_PACKET_H\n#define ESPNOW_PACKET_H\n\n#include <stdint.h>\n#include <stdio.h>\n\nstruct IEEE80211_radiotap {\n\tuint8_t version;                //= 0;\n    uint8_t pad;                    //= 0;\n    uint16_t length;                //= 0x00,0x26;\n    uint32_t present_1;             //= {0x2f, 0x40, 0x00, 0xa0};\n    uint8_t flags;          \t\t//= 10;\n    uint8_t datarate;               //0x0c\n    uint16_t channel_freq;          //0x6c, 0x09\n    uint16_t channel_flags_quarter; //0xc0, 0x00\n} __attribute__((__packed__));\n\nstruct IEEE80211_vendorspecific {\n\tuint8_t elementID;\t\t//0xdd\n\tuint8_t length;\t\t\t//0xff\n\tuint8_t\tOUI[3];\t\t\t//0x18,0xfe, 0x34\n\tuint8_t type;\t\t\t//0x04\n\tuint8_t version;\t\t//0x01\n\tuint8_t payload[127];\n\t\n} __attribute__((__packed__));\n\nstruct IEEE80211_actionframe {\n\tuint8_t category_code;\t//0x7f\n    uint8_t OUI[3];\t\t\t//0x18,0xfe, 0x34\n\tuint8_t unknown_bytes[4];\n\tstruct IEEE80211_vendorspecific content;\n} __attribute__((__packed__));\n\nstruct IEEE80211_wlan {\n\tuint8_t type;\t\t\t\t\t//0xd0\n    uint8_t flags;            \t\t//0x00\n    uint16_t duration;         //0x3a, 0x01\n    uint8_t da[6];             //0x84, 0xf3, 0xeb, 0x73, 0x55, 0x0d\n    uint8_t sa[6];             //0xf8, 0x1a, 0x67, 0xb7, 0xeb, 0x0b\n    uint8_t bssid[6];          //0x84, 0xf3, 0xeb, 0x73, 0x55, 0x0d\n    uint16_t seq;              //0x70, 0x51\n\tstruct IEEE80211_actionframe actionframe;\n    uint32_t fcs;\t\t\t\t//Random values : will be recalculated by the hrdw.\n} __attribute__((__packed__));\n\ntypedef struct {\n\n\tstruct IEEE80211_radiotap radiotap;\n\tstruct IEEE80211_wlan wlan;\n\n} __attribute__((__packed__)) ESPNOW_packet;\n\n\nvoid init_ESPNOW_packet(ESPNOW_packet *packet);\n\nint packet_to_bytes(uint8_t *bytes, int max_length, ESPNOW_packet packet);\n\nvoid print_raw_packet(uint8_t *data, int len);\n\n#endif\n"
  },
  {
    "path": "wifiRawEcho/Makefile",
    "content": "\nCC = gcc\nCFLAGS  = -g -Wall --std=c99\nINCLUDES = -I Includes/\n\ndefault: all\n\n%.o: src/%.c\n\t$(CC) $(CFLAGS) $(INCLUDES) -o bin/$@ -c $^\n\napp: main.o ESPNOW_packet.o\n\t$(CC) $(CFLAGS) -o bin/exec $(addprefix bin/,$^)\n\n\nall: clear clean app\n\nclean: \n\t$(RM) bin/*\n\nclear:\n\tclear\n"
  },
  {
    "path": "wifiRawEcho/src/ESPNOW_packet.c",
    "content": "#include \"ESPNOW_packet.h\"\n#include <stdio.h>\n#include <string.h>\n#include <assert.h>\n#include <sys/time.h>\n\n\nvoid init_ESPNOW_packet(ESPNOW_packet *packet) {\n\t//radiotap header\t\n\tpacket->radiotap.version = 0x00;\n\tpacket->radiotap.pad = 0x00;\n\tpacket->radiotap.present_1 = 0x0000000e;\n\tpacket->radiotap.flags = 0x10;\n\tpacket->radiotap.datarate = 0x6c;\n\tpacket->radiotap.channel_freq = 0x096c;\n\tpacket->radiotap.channel_flags_quarter = 0x00c0;\n\n\tpacket->radiotap.length = sizeof(packet->radiotap);\n\t\n\t\n\t//Wlan\n\tpacket->wlan.type = 0xd0;\n\tpacket->wlan.flags = 0x00;\n\tpacket->wlan.duration = 0x3a01;\n\tpacket->wlan.seq = 0x0280;//0x7051;\n\t\n\n\t//action frame\n\tpacket->wlan.actionframe.category_code = 0x7f;\n\tpacket->wlan.actionframe.OUI[0] = 0x18;\n\tpacket->wlan.actionframe.OUI[1] = 0xfe;\n\tpacket->wlan.actionframe.OUI[2] = 0x34;\n\t\n\t//vendor specific\n\tpacket->wlan.actionframe.content.elementID = 0xdd;\n\tpacket->wlan.actionframe.content.length = 0x80;//0xff;\n\tpacket->wlan.actionframe.content.OUI[0] = 0x18;\n\tpacket->wlan.actionframe.content.OUI[1] = 0xfe;\n\tpacket->wlan.actionframe.content.OUI[2] = 0x34;\n\tpacket->wlan.actionframe.content.type = 0x04;\n\tpacket->wlan.actionframe.content.version = 0x01;\n\n\t//payload\n\tfor(int i=0;i<127;i++) {\n\t\t\tpacket->wlan.actionframe.content.payload[i] = 0x13;\n\t}\n}\n\n\nint packet_to_bytes(uint8_t *bytes, int max_length, ESPNOW_packet packet) {\n\tint len = sizeof(packet);\t\n\tassert(max_length > len);\t\n\t\n\tmemcpy(bytes, &packet, len);\n\t\n\treturn len;\n}\n\n\nvoid print_raw_packet(uint8_t *data, int len)\n{\n    printf(\"----------------------new packet (len : %d)---------------------------\\n\", len);\n    int i;\n    for (i = 0; i < len; i++)\n    {\n        if (i % 16 == 0)\n            printf(\"\\n\");\n\t\telse if(i % 8 == 0)\n\t\t\tprintf(\" \");\n        printf(\"0x%02x, \", data[i]);\n    }\n    printf(\"\\n\\n\");\n}\n"
  },
  {
    "path": "wifiRawEcho/src/main.c",
    "content": "/*\nEtienne Arlaud\n*/\n\n#include <stdint.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <unistd.h>\n#include <sys/socket.h>\n#include <sys/ioctl.h>\n#include <linux/if_arp.h>\n#include <arpa/inet.h>\n#include <assert.h>\n#include <linux/filter.h>\n#include <sys/time.h>\n\n#define PRIORITY_LVL -20\n#define SOCKET_PRIORITY 7\n\n#include \"ESPNOW_packet.h\"\n\n\n#define MY_MAC 0xffffffffffff//0xf81a67b7eb0b\nstatic uint8_t broadcast_mac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};\nstatic uint8_t src_mac[6] = {0xF8, 0x1A, 0x67, 0xb7, 0xEB, 0x0B};\n//static uint8_t dest_mac[6] = {0x84, 0xf3, 0xeb, 0x73, 0x55, 0x0d}; //ESP8266\nstatic uint8_t dest_mac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};//{0xB4, 0xE6, 0x2D, 0xB5, 0x9F, 0x85};// ESP32\n\n#define MAX_PACKET_LEN 1000\n\n#define FILTER_LENGTH 53//34\n#define MAC_2_MSBytes(MAC)  ((uint64_t) MAC & (uint64_t) 0xffff00000000)>>(8*4)\n#define MAC_4_LSBytes(MAC)  (uint64_t) MAC & (((uint64_t) 1<<(4*8))-1)\n//generated with tcpdump -i wlp5s0 'type 0 subtype 0xd0 and wlan[24:4]=0x7f18fe34 and wlan[32]=221 and wlan[33:4]&0xffffff = 0x18fe34 and wlan[37]=0x4 and wlan dst f8:1a:67:b7:eb:0b' -dd\nstatic struct sock_filter bpfcode[FILTER_LENGTH] = {\n{ 0x30, 0, 0, 0x00000003 },\n{ 0x64, 0, 0, 0x00000008 },\n{ 0x7, 0, 0, 0x00000000 },\n{ 0x30, 0, 0, 0x00000002 },\n{ 0x4c, 0, 0, 0x00000000 },\n{ 0x2, 0, 0, 0x00000000 },\n{ 0x7, 0, 0, 0x00000000 },\n{ 0x50, 0, 0, 0x00000000 },\n{ 0x54, 0, 0, 0x000000fc },\n{ 0x15, 0, 42, 0x000000d0 },\n{ 0x40, 0, 0, 0x00000018 },\n{ 0x15, 0, 40, 0x7f18fe34 },\n{ 0x50, 0, 0, 0x00000020 },\n{ 0x15, 0, 38, 0x000000dd },\n{ 0x40, 0, 0, 0x00000021 },\n{ 0x54, 0, 0, 0x00ffffff },\n{ 0x15, 0, 35, 0x0018fe34 },\n{ 0x50, 0, 0, 0x00000025 },\n{ 0x15, 0, 33, 0x00000004 },\n{ 0x50, 0, 0, 0x00000000 },\n{ 0x45, 31, 0, 0x00000004 },\n{ 0x45, 0, 21, 0x00000008 },\n{ 0x50, 0, 0, 0x00000001 },\n{ 0x45, 0, 4, 0x00000001 },\n{ 0x40, 0, 0, 0x00000012 },\n{ 0x15, 0, 26, 0xffffffff },\n{ 0x48, 0, 0, 0x00000010 },\n{ 0x15, 4, 24, 0x0000ffff },\n{ 0x40, 0, 0, 0x00000006 },\n{ 0x15, 0, 22, 0xffffffff },\n{ 0x48, 0, 0, 0x00000004 },\n{ 0x15, 0, 20, 0x0000ffff },\n{ 0x50, 0, 0, 0x00000001 },\n{ 0x45, 0, 13, 0x00000002 },\n{ 0x45, 0, 4, 0x00000001 },\n{ 0x40, 0, 0, 0x0000001a },\n{ 0x15, 0, 15, 0x2db59f85 },\n{ 0x48, 0, 0, 0x00000018 },\n{ 0x15, 12, 13, 0x0000b4e6 },\n{ 0x40, 0, 0, 0x00000012 },\n{ 0x15, 0, 11, 0x2db59f85 },\n{ 0x48, 0, 0, 0x00000010 },\n{ 0x15, 8, 9, 0x0000b4e6 },\n{ 0x40, 0, 0, 0x00000006 },\n{ 0x15, 0, 7, 0xffffffff },\n{ 0x48, 0, 0, 0x00000004 },\n{ 0x15, 0, 5, 0x0000ffff },\n{ 0x40, 0, 0, 0x0000000c },\n{ 0x15, 0, 3, 0x2db59f85 },\n{ 0x48, 0, 0, 0x0000000a },\n{ 0x15, 0, 1, 0x0000b4e6 },\n{ 0x6, 0, 0, 0x00040000 },\n{ 0x6, 0, 0, 0x00000000 },\n\n\n/*\n  { 0x30, 0, 0, 0x00000003 },\n  { 0x64, 0, 0, 0x00000008 },\n  { 0x7, 0, 0, 0x00000000 },\n  { 0x30, 0, 0, 0x00000002 },\n  { 0x4c, 0, 0, 0x00000000 },\n  { 0x2, 0, 0, 0x00000000 },\n  { 0x7, 0, 0, 0x00000000 },\n  { 0x50, 0, 0, 0x00000000 },\n  { 0x54, 0, 0, 0x000000fc },\n  { 0x15, 0, 23, 0x000000d0 },\n  { 0x40, 0, 0, 0x00000018 },\n  { 0x15, 0, 21, 0x7f18fe34 },\n  { 0x50, 0, 0, 0x00000020 },\n  { 0x15, 0, 19, 0x000000dd },\n  { 0x40, 0, 0, 0x00000021 },\n  { 0x54, 0, 0, 0x00ffffff },\n  { 0x15, 0, 16, 0x0018fe34 },\n  { 0x50, 0, 0, 0x00000025 },\n  { 0x15, 0, 14, 0x00000004 },\n  { 0x50, 0, 0, 0x00000000 },\n  { 0x45, 12, 0, 0x00000004 },\n  { 0x45, 0, 6, 0x00000008 },\n  { 0x50, 0, 0, 0x00000001 },\n  { 0x45, 0, 4, 0x00000001 },\n  { 0x40, 0, 0, 0x00000012 },\n  { 0x15, 0, 7, 0x67b7eb0b },\n  { 0x48, 0, 0, 0x00000010 },\n  { 0x15, 4, 5, 0x0000f81a },\n  { 0x40, 0, 0, 0x00000006 },\n  { 0x15, 0, 3, MAC_4_LSBytes(MY_MAC) },\n  { 0x48, 0, 0, 0x00000004 },\n  { 0x15, 0, 1, MAC_2_MSBytes(MY_MAC) },\n  { 0x6, 0, 0, 0x00040000 },\n  { 0x6, 0, 0, 0x00000000 },\n*/\n};\n\nESPNOW_packet echo_packet;\nuint8_t raw_bytes[400];\n\nint create_raw_socket(char *dev, struct sock_fprog *bpf)\n{\n    struct sockaddr_ll s_dest_addr;\n    struct ifreq ifr;\n\tint priority;\n\t\n    int fd, \t\t\t//file descriptor\n\t\tioctl_errno,\t//ioctl errno\n\t\tbind_errno,\t\t//bind errno\n\t\tfilter_errno,\t//attach filter errno\n\t\tpriority_errno;\t//Set priority errno\n\t\n\tbzero(&s_dest_addr, sizeof(s_dest_addr));\n    bzero(&ifr, sizeof(ifr));\n\t\n\t\n    fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));\n    assert(fd != -1); \t\t\t//abort if error\n\n    strncpy((char *)ifr.ifr_name, dev, IFNAMSIZ); //interface\n\n    ioctl_errno = ioctl(fd, SIOCGIFINDEX, &ifr);\n    assert(ioctl_errno >= 0);\t//abort if error\n\n    s_dest_addr.sll_family = PF_PACKET;\n    //we don't use a protocol above ethernet layer, just use anything here\n    s_dest_addr.sll_protocol = htons(ETH_P_ALL);\n    s_dest_addr.sll_ifindex = ifr.ifr_ifindex;\n    s_dest_addr.sll_hatype = ARPHRD_ETHER;\n    s_dest_addr.sll_pkttype = PACKET_OTHERHOST; //PACKET_OUTGOING\n    s_dest_addr.sll_halen = ETH_ALEN;\n\tmemcpy(&(s_dest_addr.sll_addr),dest_mac, sizeof(*src_mac)*6); //MAC\n\n    bind_errno = bind(fd, (struct sockaddr *)&s_dest_addr, sizeof(s_dest_addr));\n    assert(bind_errno >= 0);\t//abort if error\n\t\n\tfilter_errno = setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, bpf, sizeof(*bpf));\n    assert(filter_errno >= 0);\n\t\n\tpriority = SOCKET_PRIORITY;\n\tpriority_errno = setsockopt(fd, SOL_SOCKET, SO_PRIORITY, &priority, sizeof(priority));\n\tassert(priority_errno ==0);\n\n    return fd;\n}\n\n\nint main(int argc, char **argv)\n{\n\tassert(argc == 2);\n\t\n\tnice(PRIORITY_LVL);\n\t\n    char *dev = argv[1];\n\n\tint packets_received = 0;\t\n\t\n\tuint8_t buff[MAX_PACKET_LEN] = {0};\n    int sock_fd = -1;\n    int s32_res = -1;\n\t\n\tstruct sock_fprog bpf = {FILTER_LENGTH, bpfcode};\n\n    sock_fd = create_raw_socket(dev, &bpf); /* Creating the raw socket */\n\n    if (sock_fd < 0)\n    {\n        perror(\"Could not create the socket\");\n        goto LABEL_CLEAN_EXIT;\n    } else {\n\t\tprintf(\"Socket created\\n\");\n\t}\n\n    fflush(stdout);\n\n    sleep(1);\n\t\n\t//init answer packet\n\tinit_ESPNOW_packet(&echo_packet);\n\tmemcpy(echo_packet.wlan.da, dest_mac, sizeof(uint8_t)*6);\n\tmemcpy(echo_packet.wlan.sa, src_mac, sizeof(uint8_t)*6);\n\tmemcpy(echo_packet.wlan.bssid, dest_mac, sizeof(uint8_t)*6);\n\t\n\n    while (1)\n    {\n\t\tint len = recvfrom(sock_fd, buff, MAX_PACKET_LEN, MSG_TRUNC, NULL, 0);\n\t\t\t\n\t\tif (len < 0)\n        {\n            perror(\"Socket receive failed or error\");\n            goto LABEL_CLEAN_EXIT;\n        }            \n\t\telse if(len > 77)\n        {\n            //printf(\"Receive packet number : %d\\n\", ++packets_received);\n            //print_raw_packet(buff, len);\n\t\t\t\n\t\t\t//generate echo\n\t\t\tmemcpy(echo_packet.wlan.actionframe.content.payload, buff+77, 16);\n\t\t\tint mypacket_len = packet_to_bytes(raw_bytes, 400, echo_packet);\n            s32_res = sendto(sock_fd, raw_bytes, mypacket_len,0,NULL,0);\n\n            if (-1 == s32_res)\n            {\n                perror(\"Socket send failed\");\n                goto LABEL_CLEAN_EXIT;\n            } else {\n              //printf(\"Echo sent\\n\\n\\n\");\n            }\n        }\n    }\n\nLABEL_CLEAN_EXIT:\n    if (sock_fd > 0)\n    {\n        close(sock_fd);\n    }\n\n    printf(\"***** Raw Socket test- end\\n\");\n\n    return EXIT_SUCCESS;\n    \n\t\n}\n"
  },
  {
    "path": "wifiRawReceiver/Makefile",
    "content": "test:\n\tmkdir -p bin\n\tgcc main.c -Wall -o bin/receiver\n\n\nclean:\n\trm -r bin\n"
  },
  {
    "path": "wifiRawReceiver/main.c",
    "content": "/*\nFlorenc Caminade\nThomas FLayols\nEtienne Arlaud\n\nReceive raw 802.11 packet and filter ESP-NOW vendor specific action frame using BPF filters.\nhttps://hackaday.io/project/161896\nhttps://github.com/thomasfla/Linux-ESPNOW\n\nAdapted from :\nhttps://stackoverflow.com/questions/10824827/raw-sockets-communication-over-wifi-receiver-not-able-to-receive-packets\n\n1/Find your wifi interface:\n$ iwconfig\n\n2/Setup your interface in monitor mode :\n$ sudo ifconfig wlp5s0 down\n$ sudo iwconfig wlp5s0 mode monitor\n$ sudo ifconfig wlp5s0 up\n\n3/Run this code as root\n*/\n#include <stdint.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <unistd.h>\n#include <sys/socket.h>\n#include <sys/ioctl.h>\n#include <linux/if_arp.h>\n#include <arpa/inet.h>\n#include <assert.h>\n#include <linux/filter.h>\n\n#define PACKET_LENGTH 400 //Approximate\n#define MYDATA 18         //0x12\n#define MAX_PACKET_LEN 1000\n\n\n/*our MAC address*/\n//{0xF8, 0x1A, 0x67, 0xB7, 0xeB, 0x0B};\n\n/*ESP8266 host MAC address*/\n//{0x84,0xF3,0xEB,0x73,0x55,0x0D};\n\n\n//filter action frame packets\n  //Equivalent for tcp dump :\n    //type 0 subtype 0xd0 and wlan[24:4]=0x7f18fe34 and wlan[32]=221 and wlan[33:4]&0xffffff = 0x18fe34 and wlan[37]=0x4\n//NB : There is no filter on source or destination addresses, so this code will 'receive' the action frames sent by this computer...\n#define FILTER_LENGTH 20\nstatic struct sock_filter bpfcode[FILTER_LENGTH] = {\n  { 0x30, 0, 0, 0x00000003 },\t// ldb [3]\t// radiotap header length : MS byte\n  { 0x64, 0, 0, 0x00000008 },\t// lsh #8\t// left shift it\n  { 0x7, 0, 0, 0x00000000 },\t// tax\t\t// 'store' it in X register\n  { 0x30, 0, 0, 0x00000002 },\t// ldb [2]\t// radiotap header length : LS byte\n  { 0x4c, 0, 0, 0x00000000 },\t// or  x\t// combine A & X to get radiotap header length in A\n  { 0x7, 0, 0, 0x00000000 },\t// tax\t\t// 'store' it in X\n  { 0x50, 0, 0, 0x00000000 },\t// ldb [x + 0]\t\t// right after radiotap header is the type and subtype\n  { 0x54, 0, 0, 0x000000fc },\t// and #0xfc\t\t// mask the interesting bits, a.k.a 0b1111 1100\n  { 0x15, 0, 10, 0x000000d0 },\t// jeq #0xd0 jt 9 jf 19\t// compare the types (0) and subtypes (0xd)\n  { 0x40, 0, 0, 0x00000018 },\t// Ld  [x + 24]\t\t\t// 24 bytes after radiotap header is the end of MAC header, so it is category and OUI (for action frame layer)\n  { 0x15, 0, 8, 0x7f18fe34 },\t// jeq #0x7f18fe34 jt 11 jf 19\t// Compare with category = 127 (Vendor specific) and OUI 18:fe:34\n  { 0x50, 0, 0, 0x00000020 },\t// ldb [x + 32]\t\t\t\t// Begining of Vendor specific content + 4 ?random? bytes : element id\n  { 0x15, 0, 6, 0x000000dd },\t// jeq #0xdd jt 13 jf 19\t\t// element id should be 221 (according to the doc)\n  { 0x40, 0, 0, 0x00000021 },\t// Ld  [x + 33]\t\t\t\t// OUI (again!) on 3 LS bytes\n  { 0x54, 0, 0, 0x00ffffff },\t// and #0xffffff\t\t\t// Mask the 3 LS bytes\n  { 0x15, 0, 3, 0x0018fe34 },\t// jeq #0x18fe34 jt 16 jf 19\t\t// Compare with OUI 18:fe:34\n  { 0x50, 0, 0, 0x00000025 },\t// ldb [x + 37]\t\t\t\t// Type\n  { 0x15, 0, 1, 0x00000004 },\t// jeq #0x4 jt 18 jf 19\t\t\t// Compare type with type 0x4 (corresponding to ESP_NOW)\n  { 0x6, 0, 0, 0x00040000 },\t// ret #262144\t// return 'True'\n  { 0x6, 0, 0, 0x00000000 },\t// ret #0\t// return 'False'\n};\n\nvoid print_packet(uint8_t *data, int len)\n{\n    printf(\"----------------------------new packet-----------------------------------\\n\");\n    int i;\n    for (i = 0; i < len; i++)\n    {\n        if (i % 16 == 0)\n            printf(\"\\n\");\n        printf(\"0x%02x, \", data[i]);\n    }\n    printf(\"\\n\\n\");\n}\n\nint create_raw_socket(char *dev, struct sock_fprog *bpf)\n{\n    struct sockaddr_ll sll;\n    struct ifreq ifr;\n    int fd, ifi, rb, attach_filter;\n\n    bzero(&sll, sizeof(sll));\n    bzero(&ifr, sizeof(ifr));\n\n    fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));\n    assert(fd != -1);\n\n    strncpy((char *)ifr.ifr_name, dev, IFNAMSIZ);\n    ifi = ioctl(fd, SIOCGIFINDEX, &ifr);\n    assert(ifi != -1);\n\n    sll.sll_protocol = htons(ETH_P_ALL);\n    sll.sll_family = PF_PACKET;\n    sll.sll_ifindex = ifr.ifr_ifindex;\n    sll.sll_pkttype = PACKET_OTHERHOST;\n\n    rb = bind(fd, (struct sockaddr *)&sll, sizeof(sll));\n    assert(rb != -1);\n\n    attach_filter = setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, bpf, sizeof(*bpf));\n    assert(attach_filter != -1);\n\n    return fd;\n}\n\nint main(int argc, char **argv)\n{\n    assert(argc == 2);\n\n    uint8_t buff[MAX_PACKET_LEN] = {0};\n    int sock_fd;\n    char *dev = argv[1];\n    struct sock_fprog bpf = {FILTER_LENGTH, bpfcode};\n\n    sock_fd = create_raw_socket(dev, &bpf); /* Creating the raw socket */\n\n    printf(\"\\n Waiting to receive packets ........ \\n\");\n\n    while (1)\n    {\n        int len = recvfrom(sock_fd, buff, MAX_PACKET_LEN, MSG_TRUNC, NULL, 0);\n\n        if (len < 0)\n        {\n            perror(\"Socket receive failed or error\");\n            break;\n        }\n        else\n        {\n            printf(\"len:%d\\n\", len);\n            print_packet(buff, len);\n        }\n    }\n    close(sock_fd);\n    return 0;\n}\n"
  },
  {
    "path": "wifiRawSender/Makefile",
    "content": "test:\n\tmkdir -p bin\n\tgcc main.c -Wall -o bin/sender\n\nclean:\n\trm -r bin\n"
  },
  {
    "path": "wifiRawSender/main.c",
    "content": "/*\nFlorenc Caminade\nThomas FLayols\n\nSend ESP-NOW vendor specific action frame example\nhttps://hackaday.io/project/161896\nhttps://github.com/thomasfla/Linux-ESPNOW\n\nAdapted from : \nhttps://stackoverflow.com/questions/10824827/raw-sockets-communication-over-wifi-receiver-not-able-to-receive-packets\n\n1/Find your wifi interface:\n$ iwconfig\n\n2/Setup your interface in monitor mode :\n$ sudo ifconfig wlp5s0 down\n$ sudo iwconfig wlp5s0 mode monitor\n$ sudo ifconfig wlp5s0 up\n\n3/Run this code as root\n*/\n#include <stdint.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <unistd.h>\n#include <sys/socket.h>\n#include <sys/ioctl.h>\n#include <linux/if_arp.h>\n#include <arpa/inet.h>\n#include <assert.h>\n\n\nstatic uint8_t gu8a_dest_mac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};\n\nint create_raw_socket(char *dev)\n{\n    struct sockaddr_ll s_dest_addr; //code from sender\n    struct ifreq ifr;\n    int fd, ifi, rb;\n\n    bzero(&s_dest_addr, sizeof(s_dest_addr));\n    bzero(&ifr, sizeof(ifr));\n\n    (void)memset(&s_dest_addr, 0, sizeof(s_dest_addr));\n\n    fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));\n    assert(fd != -1); //abort if error\n\n    strncpy((char *)ifr.ifr_name, dev, IFNAMSIZ);\n    ifi = ioctl(fd, SIOCGIFINDEX, &ifr);\n    assert(ifi != -1); //abort if error\n\n    s_dest_addr.sll_family = PF_PACKET;\n    //we don't use a protocol above ethernet layer, just use anything here\n    s_dest_addr.sll_protocol = htons(ETH_P_ALL);\n    s_dest_addr.sll_ifindex = ifr.ifr_ifindex;\n    s_dest_addr.sll_hatype = ARPHRD_ETHER;\n    s_dest_addr.sll_pkttype = PACKET_OTHERHOST; //PACKET_OUTGOING\n    s_dest_addr.sll_halen = ETH_ALEN;\n    //MAC - begin\n    s_dest_addr.sll_addr[0] = gu8a_dest_mac[0];\n    s_dest_addr.sll_addr[1] = gu8a_dest_mac[1];\n    s_dest_addr.sll_addr[2] = gu8a_dest_mac[2];\n    s_dest_addr.sll_addr[3] = gu8a_dest_mac[3];\n    s_dest_addr.sll_addr[4] = gu8a_dest_mac[4];\n    s_dest_addr.sll_addr[5] = gu8a_dest_mac[5];\n    //MAC - end\n    s_dest_addr.sll_addr[6] = 0x00; //not used\n    s_dest_addr.sll_addr[7] = 0x00; //not used\n\n    rb = bind(fd, (struct sockaddr *)&s_dest_addr, sizeof(s_dest_addr));\n    assert(rb != -1); //abort if error\n\n    return fd;\n}\n\nint main(int argc, char **argv)\n{\n    char *dev = argv[1];\n\n    int sock_fd = -1;\n    int32_t s32_res = -1;\n\n    sock_fd = create_raw_socket(dev); /* Creating the raw socket */\n\n    if (-1 == sock_fd)\n    {\n        perror(\"Could not create the socket\");\n        goto LABEL_CLEAN_EXIT;\n    }\n\n    printf(\"Socket created\\n\");\n\n    fflush(stdout);\n\n    sleep(1);\n\n    printf(\"******Sending data using raw socket over  %s \\n\", dev);\n\n    while (1)\n    {\n        uint8_t data[331] = {\n            0x00, 0x00, 0x26, 0x00, 0x2f, 0x40, 0x00, 0xa0, 0x20, 0x08, 0x00, 0xa0, 0x20, 0x08, 0x00, 0x00,\n            0xdf, 0x32, 0xfe, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0c, 0x6c, 0x09, 0xc0, 0x00, 0xd3, 0x00,\n            0x00, 0x00, 0xd3, 0x00, 0xc7, 0x01, 0xd0, 0x00, 0x3a, 0x01, 0x84, 0xf3, 0xeb, 0x73, 0x55, 0x0d,\n            0xf8, 0x1a, 0x67, 0xb7, 0xeb, 0x0b, 0x84, 0xf3, 0xeb, 0x73, 0x55, 0x0d, 0x70, 0x51, 0x7f, 0x18,\n            0xfe, 0x34, 0xa2, 0x03, 0x92, 0xb0, 0xdd, 0xff, 0x18, 0xfe, 0x34, 0x04, 0x01, 0x29, 0x12, 0x12,\n            0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12,\n            0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12,\n            0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12,\n            0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12,\n            0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12,\n            0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12,\n            0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12,\n            0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12,\n            0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12,\n            0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12,\n            0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12,\n            0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12,\n            0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12,\n            0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12,\n            0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12,\n            0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x1c, 0xd5, 0x35, 0xd3}; //FROM TLINK TO ESP\n\n        s32_res = sendto(sock_fd,data,331,0,NULL,0);\n\n        if (-1 == s32_res)\n        {\n            perror(\"Socket send failed\");\n            goto LABEL_CLEAN_EXIT;\n        }\n        int i = 0;\n        for (i = 0; i < 331; i++)\n            printf(\"%x \", data[i]);\n\n        printf(\"\\n\\n\");\n\n        usleep(100);\n    }\n\nLABEL_CLEAN_EXIT:\n    if (sock_fd > 0)\n    {\n        close(sock_fd);\n    }\n\n    printf(\"***** Raw Socket test- end\\n\");\n\n    return EXIT_SUCCESS;\n}\n"
  }
]