macsbug

Just another WordPress.com site

PacketMonitor32 with M5STACK

leave a comment »

PacketMonitor32 を M5STACK に移植しました。          2018.01.11

PacketMonitor とは 選択したWiFiチャンネルにあるデバイスの トラフィックを表示します。
表示は [ Channel ], [ RSSI (平均) ], [ Packet per Second ], [ death packets ], [ SD Card enabled ]
ボタンをクリックすると、監視している WiFiチャンネル (1-14 ch) が変更されます。
トラフィックをキャプチャする為の SDカードのサポートがあります。

M5STACK ( ESP32 + 320×240 TFT + SD Slot + Speaker + SW + BAT ):$35
M5STACK は Micro SD を入れるだけで使用できます。

LOLIN32 Pro ( ESP32-WROVER + SD Slot ):$10.78
0.96″ 128×64 OLED SSD1306 を追加しました。

TTGO T2 ( ESP-WROOM-32 + 0.95″ 96×64 Color OLED + SD Slot ):$13.55
Color OLED と SD Slot 付きです。Color OLED は小型ですが綺麗です。

PacketMonitor32spacehuhn氏により作成されたもので ハードの構成は
D-duino-32 SD + 128×64 OLED SSD1306 + micro SD card です。
spacehuhn氏に感謝致します。


マイクロSDカード:
1. 条件:16MB , FAT32 フォーマット , CLASS 10:高速なSDである事。
2. カードを取り出してボードを稼働させたい場合は「SD」が表示されなくなるまで
_ ボタンを2秒間押し続けます。
_ ボードが起動するたびに SDのルートフォルダに新しい.pcapファイルが作成されます。
_ これらのファイルは 「Wireshark 」で開くことができます。
_ 全てのパケットを常に保存することはできません。
_ 保存できるパケットが増えれば、パケットは廃棄されます。


移植:
1. ディスプレー :SSD1306 のドライバーを ILI9341 の記述に変更しました。
_ 例:display — M5.Lcd。変数の配置変更。
_ グラフ表示:ディスプレーの大きさに合わせて サイズを変更しました。
_ 例:display..drawString — M5.Lcd.drawString 。変数の配置変更。
_ 例:display..drawLine —— M5.Lcd.drawLine 。 変数の配置変更。

2. SD MMC:SD の記述に変更しました。( MMC を理解していません )
_ 例:SD_MMC — SD
_ M5STACK SDの配線
_  GPIO23=MOSI(CMD),19=MISO(D0), GPIO18=CLK, GPIO4=CS(CD/D3)

3. 条件:Packet は 毎秒の為、表示や 特にSDが高速である事が重要です。
_ シリアルモニターに「24546 bytes written for 86 ms」とか表示されます。
_ SPIの通信方式や SDの速度、ESP32ボードの構成により異なります。
_ 1秒間に行う動作:パケット受信 と 表示 と SDへの書込み。
_ SDへの書込時間が短い事が必要です。

書き込み データー:
_ 書き込みデーターの容量:1回に 約25KB です。
_ 書き込み速度:66 〜 92msec。約50sec に一度 500 〜 1000msec が起きます。


動作内容:
1. パケットの検出。
2. ディスプレーの表示。
3. SD へ書き込み。
_ 1秒間に パケット検出、ディスプレー表示、SD書き込み が行われます。
_ ディスプレーの表示 と SD へ書き込み が高速である事が 望まれます。
_ スケッチの中で
_ SD への書き込み速度が 450msec とかになると 書き込まれません。
_ テクニック:初期設定で SPIの速度「 SD.begin(sd_ss, SPI, 20000000);」
_  にする。SPI.begin 設定の前に SPI.end(); で SDを確実に設定します。
_  SPI は 通常 4MHz ですが 例として「SD.begin(sd_ss, SPI, 24000000);」
_  で 24MHz に設定し高速になります。

SD書き込み速度:シリアルモニターで観測。
_ 書込み速度が速い程 Packet のモニターに時間を使用する事が出来ます。
_ たまにSDへの書込み速度が低下する場所があります。
_ M5STACK は 約150msec。
_ LOLIN32 Pro は 約50msec。ただし不安定です。
_ TTGO T2 は 約50msec。

Wireshark を使用した 解析表示の例:


課題:
1. スケッチの書き方で速度が変わります。特に SDの setup の設定です。
_ SPI の設定が複数ある場合、SPI.end(); が必要です。
2. LOLIN32 Pro は SD の認識でロスする場合があり リトライで対応しています。
3. 速度や間欠部は 課題です。


参考:
1. acketMonitor32 Interface Explaination:表示とボタンの説明。
2. spacehuhn / PacketMonitor32
3. spacehuhn / ESP8266 PakcketMonitor
4. tindle:WiFi Packet Monitor V3 (Preflashed D-duino-32 SD)
5. Aliexpress:DSTIKE Store:WiFi Packet Monitor V3(Preflashed D-duino-32 SD)
6. YouTube:PacketMonitor32
7. M5STACK Pinout


感想:
1. PacketMonitor32 を作成された spacehuhn氏のリストは奥深く
_ 私には 理解できない高度なレベルの記述が多々あります。
_ よって 知りえる程度でスケッチを変更しました。
_ 特に感心したのは グラフと横スクロール の方法です。
_ この方法をマスターすると素晴らしい表現が出来るかと思います。
2. SD と SDMMC:
_ SD式の信号は D3/CD, MOSI(CMD), CLK, MISO/D0
_ で 4本配線の回路になっています
_ SDMMC式の信号は D2, C2/D3, MOSI/CMD, CLK, MISO(D0), D1
_ で 6本配線の回路になっています
_ 6本配線は 「D-Duino32 SD」と「魔法の大鍋氏のESP32ボード」があります。
_ 魔法の大鍋氏は製作時に ESP社の基本に基づき作られました。
_ PacketMonitor32 のボードは SDMMC回路のボードと思われます。
_ LOLIN32 Pro の回路は SDMMC接続の回路になっています。
_ D2=GPIO12, C2/D3=13, MOSI/CMD=15, CLK=14, MISO(D0)=2,D1=4
_ です。
_ M5STACK は SD 回路です。
_ TTGO T2 は SD 回路です。
_ 他の SD 付きの ESP32 ボードは SD式で構成されています。
2. SD CARD:
_ 使用した SD は マイクロSD 16G FAT32 Class 10 です。
_ SD を理解していなく 又 手持ちにある SD は マイクロSDです。
_ ESP32 のライブラリーに SD と SDMMC のサンプルがあります。
_ これは マイクロSDで動作します。(意味が解っていないかも)
_ PacketMonitor32 のスケッチは SDMMC を使用しています。
_ この SDMMC の記述では書込みエラーがでて使用できません。
_ SDMMC の記述を SD に変更して動くようにしました。
3. 画面の大きさ:
_ 小さい画面の場合、スクロール等の工夫が必要でプログラムが負担です。
_ M5STACK の画面は大きく 縦側に数値を表示し見やすくなりました。
_ 工夫すると見栄えの良い物ができますし高機能になります。
4. アクリル台:
_ ダイソー:L型 カードスタンド です。6.5 x4cm。2個で100円。


スケッチ:PacketMonitor32 of M5STACK.

訂正事項:77行目の M5.Lcd.drawString( “Made with <_3 by”, 24, 44);
_ の 「<_3 」は「 _ 」 を取り除いて「<3」に変更してください。
_ 装置がネットに接続されいますと 画面に素晴らしい文字が表示されます。
_ 205行目の「:D_ *」は「_ 」 を取り除いて「:D *」にしてください。emojiです。
補足:フォント “Free_Fonts.h” をスケッチ内に入れておきます。
補足:LOLIN32 Pro と TTGO T2 のリストは省略致します。

// PacketMonitor32 of M5STACK : 2018.01.11 macsbug
// spacehuhn/PacketMonitor32 : 
//  https://github.com/spacehuhn/PacketMonitor32/
// DISPLAY: Channel,RSSI,Packet per Second,deauth packets,SD Card enabled
// Button : click to change channel hold to dis/enable SD
// SD : GPIO4=CS(CD/D3), 23=MOSI(CMD), 18=CLK, 19=MISO(D0)
//--------------------------------------------------------------------
#include <M5Stack.h>
#include "Free_Fonts.h"
#include <SPI.h>
#include "freertos/FreeRTOS.h"
#include "esp_wifi.h"
#include "esp_wifi_types.h"
#include "esp_system.h"
#include "esp_event.h"
#include "esp_event_loop.h"
#include "nvs_flash.h"
#include <stdio.h>
#include <string>
#include <cstddef>
#include <Preferences.h>
#define MAX_CH 14     // 1-14ch(1-11 US,1-13 EU and 1-14 Japan)
#define SNAP_LEN 2324 // max len of each recieved packet
#define BUTTON_PIN 39 // button to change the channel
#define MAX_X 315     // 128
#define MAX_Y 230     //  51
#if CONFIG_FREERTOS_UNICORE
#define RUNNING_CORE 0
#else
#define RUNNING_CORE 1
#endif
#include "Buffer.h"
#include "FS.h"
#include "SD.h"
enum { sd_sck = 18, sd_miso = 19, sd_mosi = 23, sd_ss = 4 };
esp_err_t event_handler(void* ctx,system_event_t* event){return ESP_OK;}
/* ===== run-time variables ===== */
Buffer sdBuffer;
Preferences preferences;
bool useSD = false;
bool buttonPressed = false;
bool buttonEnabled = true;
uint32_t lastDrawTime;
uint32_t lastButtonTime;
uint32_t tmpPacketCounter;
uint32_t pkts[MAX_X]; // here the packets per second will be saved
uint32_t deauths = 0; // deauth frames per second
unsigned int ch = 1;  // current 802.11 channel
int rssiSum;

// ===== main program ================================================
void setup() {
  // Serial ----------------------------------------------------------
  Serial.begin(115200);
  // System & WiFi ---------------------------------------------------
  nvs_flash_init();
  tcpip_adapter_init();
  wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
  ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL));
  ESP_ERROR_CHECK(esp_wifi_init(&cfg));
  //ESP_ERROR_CHECK(esp_wifi_set_country(WIFI_COUNTRY_EU));
  ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM));
  ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_NULL));
  ESP_ERROR_CHECK(esp_wifi_start());
  esp_wifi_set_channel(ch, WIFI_SECOND_CHAN_NONE);
  // display -------------------------------------------------------
  M5.begin();
  dacWrite(25, 0); // Speaker OFF
  M5.Lcd.fillScreen(TFT_BLACK);
  M5.Lcd.setTextColor(WHITE, BLACK);
  M5.Lcd.setTextSize(1);
  M5.Lcd.setRotation(0);
  /* show start screen */
  M5.Lcd.fillScreen(BLACK);
  M5.Lcd.setFreeFont(FM12);
  M5.Lcd.drawString( "PacketMonitor32", 6, 24);
  M5.Lcd.drawString( "Made with <_3 by", 24, 44);
  M5.Lcd.drawString( "@Spacehuhn", 29, 64);
  delay(3000);
  M5.Lcd.fillScreen(BLACK);
  M5.Lcd.setFreeFont(FM9);
  int s = 10, a = 0;
  M5.Lcd.setTextColor( WHITE, BLACK);  // Pkts Scale
  for ( int ypos = MAX_Y; ypos > 120; ypos = ypos - s ){
    M5.Lcd.setTextDatum(MR_DATUM);
    M5.Lcd.drawString(String( MAX_Y - ypos ),30, ypos - 1 - a);
    a = a + 10;
  }
  M5.Lcd.setFreeFont(FM9);
  M5.Lcd.setTextDatum(TL_DATUM);
  M5.Lcd.fillRect(0, 0, 320, 20, BLUE);
  // SD card ---------------------------------------------------------
  SPI.end();
  SPI.begin(sd_sck, sd_miso, sd_mosi, sd_ss); 
  SD.begin(sd_ss, SPI, 24000000);
  if(!SD.begin(sd_ss,SPI)){
    Serial.println("Card Mount Failed");return;
  }
  sdBuffer = Buffer();
  if (setupSD()){sdBuffer.open(&SD);Serial.println(" SD CHECK OPEN");
  }
  // I/O -----------------------------------------------------------
  pinMode(BUTTON_PIN, INPUT_PULLUP);
  // second core ----------------------------------------------------
  xTaskCreatePinnedToCore(
    coreTask,               /* Function to implement the task */
    "coreTask",             /* Name of the task */
    2500,                   /* Stack size in words */
    NULL,                   /* Task input parameter */
    0,                      /* Priority of the task */
    NULL,                   /* Task handle. */
    RUNNING_CORE);          /* Core where the task should run */
  // start Wifi sniffer ---------------------------------------------
  esp_wifi_set_promiscuous_rx_cb(&wifi_promiscuous);
  esp_wifi_set_promiscuous(true);
}
// ===== main program ================================================
void loop() {
  vTaskDelay(portMAX_DELAY);
  
}
// ===== functions ===================================================
double getMultiplicator() {
  uint32_t maxVal = 1;
  for (int i = 0; i < MAX_X; i++) {
    if (pkts[i] > maxVal) maxVal = pkts[i];
  }
  if (maxVal > MAX_Y) return (double)MAX_Y / (double)maxVal;
  else return 1;
}
// ===== functions ===================================================
void setChannel(int newChannel) {
  ch = newChannel;
  if (ch > MAX_CH || ch < 1) ch = 1;
  preferences.begin("packetmonitor32", false);
  preferences.putUInt("channel", ch);
  preferences.end();
  esp_wifi_set_promiscuous(false);
  esp_wifi_set_channel(ch, WIFI_SECOND_CHAN_NONE);
  esp_wifi_set_promiscuous_rx_cb(&wifi_promiscuous);
  esp_wifi_set_promiscuous(true);
}
// ===== functions ===================================================
bool setupSD() {
  if (!SD.begin(sd_ss, SPI)) {
    Serial.println("Card Mount Failed"); return false;
  }
  uint8_t cardType = SD.cardType();
  if (cardType == CARD_NONE) {
    Serial.println("No SD_MMC card attached"); return false;
  }
  Serial.print("SD_MMC Card Type: ");
  if (cardType == CARD_MMC){         Serial.println("MMC");
  } else if (cardType == CARD_SD){   Serial.println("SDSC");
  } else if (cardType == CARD_SDHC){ Serial.println("SDHC");
  } else {                           Serial.println("UNKNOWN");
  }
  uint64_t cardSize = SD.cardSize() / (1024 * 1024);
  Serial.printf("SD_MMC Card Size: %lluMB\n", cardSize);
  return true;
}
// ===== functions ===================================================
void wifi_promiscuous(void* buf, wifi_promiscuous_pkt_type_t type) {
  wifi_promiscuous_pkt_t* pkt = (wifi_promiscuous_pkt_t*)buf;
  wifi_pkt_rx_ctrl_t ctrl = (wifi_pkt_rx_ctrl_t)pkt->rx_ctrl;
  if (type == WIFI_PKT_MGMT && 
     (pkt->payload[0] == 0xA0 || pkt->payload[0] == 0xC0 )) deauths++;
  if (type == WIFI_PKT_MISC) return;   // wrong packet type
  if (ctrl.sig_len > SNAP_LEN) return; // packet too long
  uint32_t packetLength = ctrl.sig_len;
  if (type == WIFI_PKT_MGMT) packetLength -= 4; 
  // fix for known bug in the IDF
  // https://github.com/espressif/esp-idf/issues/886
  //Serial.print(".");
  tmpPacketCounter++;
  rssiSum += ctrl.rssi;
  if (useSD) sdBuffer.addPacket(pkt->payload, packetLength);
}
// ===== functions ===================================================
void draw() {
  double multiplicator = getMultiplicator();
  int len, rssi;
  if (pkts[MAX_X - 1] > 0) rssi = rssiSum / (int)pkts[MAX_X - 1];
  else rssi = rssiSum;
  String p = (String)ch + " | " + (String)rssi + " | Pkts " +
     (String)tmpPacketCounter + " [" + deauths + "]" +
     (useSD ? " | SD" : "");
  M5.Lcd.setTextColor(WHITE,BLUE);                    // packet
  M5.Lcd.drawString(p + "  ", 10, 2);                 // string DRAW
  M5.Lcd.drawLine(40,MAX_Y-200,MAX_X,MAX_Y-200,GREEN);// MAX LINE DRAW
  for (int i = 40; i < MAX_X; i++) {                  // LINE DRAW
    len = pkts[i] * multiplicator;
    len = len * 2;
    if ( (MAX_Y - len) < (MAX_Y - 200)){ len = 200;}  // over flow
    M5.Lcd.drawLine(i, MAX_Y, i, 31, TFT_BLACK);      // LINE EARSE
    M5.Lcd.drawLine(i, MAX_Y, i, MAX_Y - len , GREEN);// LINE DRAW
    if (i < MAX_X - 1) pkts[i] = pkts[i + 1];
  }
}
// ===== functions ===================================================
void coreTask( void * p ) {
  uint32_t currentTime;
  while (true) {
    currentTime = millis();
    /* bit of spaghetti code, have to clean this up later :D_ */
    // check button
    if (digitalRead(BUTTON_PIN) == LOW) {
      M5.Lcd.fillRect(0, 0, 320, 20, BLUE);
      if (buttonEnabled) {
        if (!buttonPressed) {
          buttonPressed = true;
          lastButtonTime = currentTime;
        } else if (currentTime - lastButtonTime >= 2000){
          if (useSD) {
            useSD = false;
            sdBuffer.close(&SD);
            draw();
          } else {
            if (setupSD())
              sdBuffer.open(&SD);
            draw();
          }
          buttonPressed = false;
          buttonEnabled = false;
        }
      }
    } else {
      if (buttonPressed) {
        setChannel(ch + 1);
        draw();
      }
      buttonPressed = false;
      buttonEnabled = true;
    }
    // save buffer to SD
    if (useSD) sdBuffer.save(&SD);
    // draw Display
    if ( currentTime - lastDrawTime > 1000 ) {
      lastDrawTime = currentTime;
      // Serial.printf("\nFree RAM %u %u\n", 
      // heap_caps_get_minimum_free_size(MALLOC_CAP_8BIT),
      // heap_caps_get_minimum_free_size(MALLOC_CAP_32BIT));
      // for debug purposes
      pkts[MAX_X - 1] = tmpPacketCounter;
      draw();
      //Serial.println((String)pkts[MAX_X - 1]);
      tmpPacketCounter = 0;
      deauths = 0;
      rssiSum = 0;
    }
    // Serial input
    if (Serial.available()) {
      ch = Serial.readString().toInt();
      if (ch < 1 || ch > 14) ch = 1;
      setChannel(ch);
    }
  }
}
// ===================================================================


広告

Written by macsbug

1月 11, 2018 @ 1:00 am

カテゴリー: ESP32

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中

%d人のブロガーが「いいね」をつけました。