ESP8266/ESP32+OLED12864简单WiFi扫描器 支持OTA

2023-05-16

功能描述

OLED显示SSID
全中文界面
支持中文SSID
Arduino OTA支持

硬件准备

ESP8266:NodeMCU WiFi
ESP32:WIFI+BLE+OLED开发板(OLED控制芯片:SSD1315兼容SSD1306)
OLED:1.3’ 控制芯片:SH1106

软件准备

Arduino IDE
U8g2lib

连线

按键:GPIO 0
板载LED:GPIO 16
GND -
VCC - 3.3v
OLED SCK - GPIO 14 (NodeMCU D5)
OLED MOSI - GPIO 13(NodeMCU D7)
OLED CS - GPIO 15 (NodeMCU D8)
OLED DC - GPIO 2 (NodeMCU D4)
连线图

程序

/*
   WiFiScannerOLED.ino -- 一个简易ESP8266/ESP32网络扫描器.
   扫描结果将会被显示在OLED12864上.
   可以通过OTA进行升级
   Written by CNflysky 20.3.10
   last edited by CNflysky at 20.3.21*/

#define BOARD 32
/* 板卡选择,ESP32=32,ESP8266=8266 */
#if (BOARD == 32)
#include <WiFi.h>
#elif (BOARD == 8266)
#include <ESP8266WiFi.h>
#endif

#include <WiFiUdp.h>
#include <ArduinoOTA.h>
#include <U8g2lib.h>
#include <cstring>
#define LED 16      /* 板载LED选择 */
#define BUTTON 0    /* 板载按键选择,这里选择的是板上的Flash(Boot)按键作为扫描键 */
int ssids = 0;
bool networkfound = false;
const char *ssid = "TP-LINK_18A4";   /* 你的SSID */
const char *password = "jse105724482";   /* 你的密码 */
int state = 0; /* 0:正常运行 1:OTA升级模式 */

/* OLED构造函数,按需修改即可 */
U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2( U8G2_R0, /* clock=*/ 4, /* data=*/ 5, /* reset=*/ U8X8_PIN_NONE );

typedef enum {
  BUTTON_CLICK,
  BUTTON_LONG_PRESS,
  BUTTON_NOT_PRESSED
} buttonState;

struct wifis_t {
  String  ssid;
  String  encryption;
  int rssi;
};

void setup() {
  /* 初始化开发板 */
  pinMode( LED, OUTPUT );
  digitalWrite( LED, HIGH );      /* 本人开发板上的LED是低电平触发,所以将LED脚拉高,请按需选择 */
  u8g2.setFont( u8g2_font_wqy12_t_gb2312 );
  u8g2.begin();
  u8g2.enableUTF8Print();
  displayWelcome();               /* 显示欢迎语,可去除 */
  WiFi.mode( WIFI_STA );
  //配置OTA函数
  ArduinoOTA.onStart( handleOTAStart );
  ArduinoOTA.onEnd( handleOTAEnd );
  ArduinoOTA.onProgress( handleOTAProgress );
  ArduinoOTA.onError( handleOTAError );
  delay( 100 );
}

void handleOTA() {
  char * str = "升级模式";
  char * str2 = "连接中...";
  char * str3 = "未搜索到预保存SSID";
  u8g2.clearBuffer();
  u8g2.drawUTF8( u8g2.getDisplayWidth() / 2 - u8g2.getUTF8Width( str ) / 2, u8g2.getMaxCharHeight(), str );
  if (networkfound == false) {
    u8g2.sendBuffer();
    int count = WiFi.scanNetworks();
    for (int i = 0; i < count; ++i) {
      if (!strcmp(ssid, WiFi.SSID(i).c_str())) {
        networkfound = true;
      }
    }
  }
  if (networkfound == false) {
    u8g2.drawUTF8( 0, u8g2.getMaxCharHeight() * 2, str3 );
    u8g2.sendBuffer();
    delay(3000);
  } else {
    if (WiFi.status() != WL_CONNECTED) {
      u8g2.drawUTF8( u8g2.getDisplayWidth() / 2 - u8g2.getUTF8Width( str ) / 2, u8g2.getMaxCharHeight() * 2, str2 );
      WiFi.begin(ssid, password);
      delay(1000);
      if (WiFi.status() != WL_CONNECTED)
        WiFi.reconnect();
    } else {
      u8g2.setCursor( 0, u8g2.getMaxCharHeight() * 2 );
      u8g2.print( WiFi.localIP() );
      ArduinoOTA.begin();
      ArduinoOTA.handle();
    }
    u8g2.sendBuffer();
  }
}
void handleOTAStart() {
  digitalWrite( LED, LOW );
}

void handleOTAEnd() {
  digitalWrite( LED, HIGH );
  char * str  = "升级完成";
  char * str2 = "三秒后自动重启";
  u8g2.clearBuffer();
  u8g2.drawUTF8( u8g2.getDisplayWidth() / 2 - u8g2.getUTF8Width( str ) / 2, u8g2.getMaxCharHeight(), str );
  u8g2.drawUTF8( u8g2.getDisplayWidth() / 2 - u8g2.getUTF8Width( str2 ) / 2, u8g2.getMaxCharHeight() * 2, str2 );
  u8g2.sendBuffer();
  delay( 3000 );
  ESP.restart();
}

void handleOTAError( ota_error_t error ) {
  char * str = "升级失败";
  u8g2.clearBuffer();
  u8g2.drawUTF8( u8g2.getDisplayWidth() / 2 - u8g2.getUTF8Width( str ) / 2, u8g2.getDisplayHeight() / 2 + u8g2.getMaxCharHeight() / 2, str );
  u8g2.sendBuffer();
}

void handleOTAProgress( unsigned int progress, unsigned int total ) {
  u8g2.clearBuffer();
  u8g2.setCursor( 0, u8g2.getMaxCharHeight() );
  u8g2.print( "升级中:" );
  u8g2.print( (progress / (total / 100) ) );
  u8g2.print( "%" );
  u8g2.sendBuffer();
}

struct wifis_t *getWiFisInfo( int count ) {
  wifis_t *wifis = new wifis_t[count];
  wifis_t switcher;
  for ( int i = 0; i < count; ++i ) {
    wifis[i].ssid = WiFi.SSID( i );
    wifis[i].rssi = WiFi.RSSI( i );
    /* 由于ESP8266和ESP32在加密方式的常量定义上有所不同,这里分为两部分 */
#if (BOARD == 32)
    switch ( WiFi.encryptionType( i ) ) {
      case WIFI_AUTH_OPEN:
        wifis[i].encryption = "Open";
        break;
      case WIFI_AUTH_WEP:
        wifis[i].encryption = "WEP";
        break;
      case WIFI_AUTH_WPA_PSK:
        wifis[i].encryption = "WPA";
        break;
      case WIFI_AUTH_WPA2_PSK:
        wifis[i].encryption = "WPA2";
        break;
      case WIFI_AUTH_WPA_WPA2_PSK:
        wifis[i].encryption = "WPA/WPA2";
        break;
      case WIFI_AUTH_WPA2_ENTERPRISE:
        wifis[i].encryption = "WPA2 EP";
        break;
    }
#elif (BOARD == 8266)
    switch ( WiFi.encryptionType( i ) ) {
      case ENC_TYPE_NONE:
        wifis[i].encryption = "Open";
        break;
      case ENC_TYPE_WEP:
        wifis[i].encryption = "WEP";
        break;
      case ENC_TYPE_TKIP:
        wifis[i].encryption = "WPA";
        break;
      case ENC_TYPE_CCMP:
        wifis[i].encryption = "WPA2";
        break;
      case ENC_TYPE_AUTO:
        wifis[i].encryption = "WPA/WPA2";
        break;
    }
#endif
    /* wifis[i].encryption=WiFi.encryptionType(i); */
  }
  /* 排序 */
  for ( int i = 0; i < count; i++ ) {
    for ( int j = 0; j < count; j++ ) {
      if ( wifis[i].rssi * -1 < wifis[j].rssi * -1 ) {
        switcher = wifis[i];
        wifis[i] = wifis[j];
        wifis[j] = switcher;
      }
    }
  }
  return (wifis);
}

void displayWelcome() {
  char *str = "正在启动...";
  u8g2.clearBuffer();
  /* 将字符串显示在屏幕中央 */
  u8g2.drawUTF8( u8g2.getDisplayWidth() / 2 - u8g2.getUTF8Width( str ) / 2, u8g2.getDisplayHeight() / 2 + u8g2.getMaxCharHeight() / 2, str );
  u8g2.sendBuffer();
  /* while(1); */
}

int getButtonState( int pin ) {
  pinMode( pin, INPUT );
  if ( digitalRead( pin ) == LOW ) { /* 本人开发板上的按键按下为低电平,请根据你自己的情况修改 */
    int pressTime = millis();
    while ( digitalRead( pin ) == LOW );
    int releaseTime = millis();
    if ( releaseTime - pressTime <= 500 && releaseTime - pressTime >= 20 )
      return (BUTTON_CLICK);
    else if ( releaseTime - pressTime > 2000 ) {
      return (BUTTON_LONG_PRESS);
    }
  } else return (BUTTON_NOT_PRESSED);
}

void displaySSIDs( int count, wifis_t *wifis ) {
  int y = u8g2.getMaxCharHeight();
  int offset  = 11;
  u8g2.drawUTF8( 0, y - 3, "网络名称" );
  u8g2.drawUTF8( (u8g2.getDisplayWidth() - u8g2.getMaxCharWidth() * 3) - 10, y - 3, "强度" );
  u8g2.drawUTF8( u8g2.getDisplayWidth() - u8g2.getMaxCharWidth() * 2 + 3, y - 3, "安全" );
  for ( int i = 0; i < count; i++ ) {
    if ( y < u8g2.getDisplayHeight() ) {
      u8g2.setCursor( 0, y + offset );
      u8g2.print( wifis[i].ssid );
      /* Serial.println(wifis[i].ssid.isAlpha()); */
      u8g2.print( " " );
      u8g2.setCursor( (u8g2.getDisplayWidth() - u8g2.getMaxCharWidth() * 3) - 1, y + offset );
      u8g2.print( wifis[i].rssi * -1 );
      u8g2.print( " " );
      u8g2.setCursor( u8g2.getDisplayWidth() - u8g2.getMaxCharWidth() * 2 + 3, y + offset );
      /* 由于屏幕大小限制,没有显示全加密方式 */
      if ( wifis[i].encryption != "Open" )
        u8g2.print( "加密" );
      else
        u8g2.print( "开放" );
      /* u8g2.println(wifis[i].encryption); */
      y += u8g2.getMaxCharHeight();
    }
  }
}

void messageWhileNoSSID() {
  char * str  = "没有发现WiFi";
  char * str2 = "按下按键开始扫描";
  u8g2.clearBuffer();
  u8g2.drawUTF8( u8g2.getDisplayWidth() / 2 - u8g2.getUTF8Width( str ) / 2, u8g2.getMaxCharHeight(), str );
  u8g2.drawUTF8( u8g2.getDisplayWidth() / 2 - u8g2.getUTF8Width( str2 ) / 2, u8g2.getMaxCharHeight() * 2, str2 );
  u8g2.sendBuffer();
}

void scanNetwork() {
  digitalWrite( LED, LOW );
  u8g2.clearBuffer();
  char * str = "扫描中...";
  u8g2.drawUTF8( u8g2.getDisplayWidth() / 2 - u8g2.getUTF8Width( str ) / 2, u8g2.getMaxCharHeight(), str );
  u8g2.sendBuffer();
  ssids = WiFi.scanNetworks();
  digitalWrite( LED, HIGH );
}

void loop() {
  int bstate = getButtonState( BUTTON );
  if ( bstate == BUTTON_CLICK && state != 1 ) {
    scanNetwork();
  } else if ( bstate == BUTTON_LONG_PRESS && state != 1 ) {
    state = 1;
  } else {
    if ( ssids > 0 && state == 0 ) {
      wifis_t *wifis = getWiFisInfo( ssids );
      u8g2.clearBuffer();
      displaySSIDs( ssids, wifis );
      u8g2.sendBuffer();
      delete[] wifis;
    } else if ( state == 1 ) {
      handleOTA();
    } else {
      messageWhileNoSSID();
    }
  }
}

成果图

在这里插入图片描述

如何使用OTA升级功能

在代码中修改SSID和密码为你自己的WiFi名称和密码
在开机状态下,长按按钮三到五秒,松开后进入如下界面:在这里插入图片描述
其中显示的IP地址 xxx.xxx.xxx.xxx就是ESP连接WiFi后得到的的IP地址。
打开Arduino IDE,检查工具/端口菜单,你应该会看到一个网络端口:
ESPxx-xxxxxxxxxxxx at xxx.xxx.xxx.xxx:
在这里插入图片描述
选择这个端口之后点击上传即可。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ESP8266/ESP32+OLED12864简单WiFi扫描器 支持OTA 的相关文章

  • 多点连接 - 在 Swift 5 中获取文件传输(互联网)速度和文件大小

    我正在点对点传输照片 一切正常 但我无法获得照片 文件 传输速度 例如互联网速度 与MB 一样 文件也被传输 其次我想获取该文件的大小 我们使用数据格式传递照片MCSession 由于隐私原因 我无法在此处添加项目代码 但我将分享我关注的参
  • 有没有办法在 python/opencv 中从单摄像头视频生成实时深度图?

    我试图将单个图像转换为其深度图 但我找不到任何有用的教程或文档 我想使用 opencv 但是如果您知道使用张量流等获取深度图的方法 我很高兴听到它 有很多关于立体视觉的教程 但我想让它更便宜 因为它是一个帮助盲人的项目 我目前正在使用 es
  • Intent.setAction()和intent.getAction()在BroadcastReceiver中不起作用

    我正在使用 BroadCastReceiver 来允许用户执行离线事件 问题是它永远不会进入内部intent getAction equals beenthereclicked 如果我尝试在点击beenThereView后几秒钟打开wifi
  • 如何学习Linux无线驱动(mac80211)的结构?

    Linux无线驱动mac80211中有这么多的结构 像struct net device struct ieee80211 hw struct ieee80211 vif and struct ieee80211 local等等 如此多的结
  • VSCode 上的 PlatformIO 未编译:collect2.exe:错误:ld 返回 1 退出状态

    我最近不得不擦拭我的计算机 在一切准备就绪并运行之后 是时候打开我之前正在处理的一些 ESP32 程序了 发现 VSCode 上的 Platform IO 将不再编译 运行编译器后 我收到以下错误 Compiling pio build e
  • iOS 检查 WiFi 辅助是否已启用

    我正在尝试检查 WiFi 辅助是否已启用 当我连接到接入点获取一些数据时遇到问题 当我的连接状况不佳时 我的蜂窝数据会被使用并干扰我的接入点 有什么方法可以检查该选项是否启用 好吧 我想我能帮上一点忙 你需要check SCNetworkR
  • 使用 C# 配置 Wifi 设置

    如何使用 C 紧凑框架 为 Win Mobile 应用程序配置 Wifi 设置 所以交易是 配置网络 隐藏APP的SSID 使用 TKIP 进行 WPA 身份验证 强制用户和密码 不会提示最终用户进行身份验证 看看智能设备框架 http w
  • 我可以枚举可用的 WLAN 吗?

    我想获取我周围可用的 WLAN 的信息 例如 SSID 这可能吗 Edit 可能是 通过市场认证 的意思 不 这在当前的 API 集中不可用 而且我认为 Mango 集中也没有提到它
  • 我可以在 Android 中找到我的接入点的 MAC 地址吗?

    我的 Android 应用程序可以找到它所连接的 Wifi 接入点的 MAC 地址吗 android net wifi WifiInfo getMacAddress 的文档未提供任何详细信息 See http developer andro
  • 无法理解 PcapNG 文件中的 802.11 数据帧格式

    I have PcapNG由 Wireshark 创建的文件 我尝试用它来解析python pcapng However I cannot figure out how to reconcile the output I receive f
  • 如何在不连续重置的情况下将esp8266从深度睡眠中唤醒

    我正在使用 esp8266 构建 IR 到 wifi 桥接器 基本上 我正在构建一个连接到红外遥控器内的 esp8266 的红外接收器 以通过 wifi 将接收到的红外远程按键转发到服务器 我使用的是 Wemos D1 Mini 我已经让
  • 解释 802.11 Wireshark 跟踪中的帧控制字节

    我有一个 Wi Fi 捕获 pcap 我正在分析并发现 802 11 规范与 Wireshark 对数据的解释之间存在不一致之处 具体来说 我想要分解的是 2 字节 802 11帧控制 field 取自http www4 ncsu edu
  • 如何在 Mobile Safari 中检测 3G 与 Wifi 连接?

    我特别询问的是移动网页上的 javascript 而不是 Objective C 应用程序 是否有像 Apple Reachability for javascript 这样的东西 以便我可以知道 Edge 3G 或 Wifi 连接何时建立
  • Android手机休眠时网络访问

    我正在使用警报组合 设置为AlarmManager 和后台服务定期同步我的应用程序中的数据 我遇到的唯一问题是 当睡眠策略终止 Wi Fi 连接时 同步将不再起作用 有没有办法 唤醒 已进入睡眠状态的 Wi Fi 连接 GMail 以某种方
  • 通过 Wi-Fi 运行/安装/调试 Android 应用程序?

    我认为有一种方法可以通过 Wi Fi 测试开发中的应用程序 这可能吗 我希望能够摆脱手机的束缚并进行无线开发 参见论坛帖子 通过USB连接设备并确保调试正常 adb tcpip 5555 这使得设备开始侦听端口 5555 上的连接 查找设备
  • 连接 Wi-Fi 网络时如何使用蜂窝数据?

    我期待在连接 Wi Fi 时使用蜂窝数据 Yi行车记录仪的工作原理是这样的 易相机制作软AP iOS 或 Android 手机连接 Wi Fi YI和Phone之间建立内部网络 一般情况下 手机不能上网 但是 在Yi网络中 手机可以使用互联
  • iOS6 在非越狱设备上切换 WiFi

    我正在开发一个内部 iOS 应用程序 不适用于苹果商店 所以我很乐意使用私有 API 并且我希望能够以编程方式打开或关闭 wifi 我想要这样做的原因是 对于某些 WiFi 路由器 每当互联网连接中断时 iPad 就无法恢复 WiFi 不过
  • Flutter IOS 使用连接或 wifi 插件读取 wifi 名称

    这个问题是类似的这个问题 https stackoverflow com questions 52498906 how to get the wifi namessid of the currently connected wifi in
  • Android wifi的信号强度[重复]

    这个问题在这里已经有答案了 可能的重复 Android 如何监控WiFi信号强度 https stackoverflow com questions 1206891 android how to monitor wifi signal st
  • 如何打开实际上已关闭的 Wifi 适配器的无线电?

    我在用着托管无线网络 http managedwifi codeplex com获取我的 Wifi 适配器的无线电状态 如果收音机实际上已关闭 如何将其打开 像这样的东西 WlanClient wlanClient new WlanClie

随机推荐