Saturday, November 13, 2021

0000 0000 0111 1011

WiFi Repeater (Part One)

Part of the program to monitor and automate some things around the property naturally enough includes extending the WiFi network to cover a wider area. There are a number of ways of doing this, including:

1. Buying a decent router and channelling heaps of power into it for coverage
2. Buying WiFi extenders/repeaters and wiring them in all over the place
3. Coming up with some half-baked plan to use $1 ESP-01 devices running on solar power (in Tasmania!)

Of these options, which do you think this post is essentially about? 


There are a number of options for setting up such a (cheap) extended network, and it may take a few blogs/videos to explore and evaluate some options. On my list is the following:

1. Can I program the ESP-01 to accept home WiFi?
2. Which extender/repeater software for the ESP-01 suits my needs?
3. Test the network under various conditions to help me make the decision
4. Work on Solar/Battery combinations that work for spreading the network around a rural property 
5. Design and 3D print a weather-resistant project box

On the programming front, the little adapters are great, however there seem to be two main types. One is just a cradle for the ESP-01 and needs some soldering and a button added to be used as a programmer (see video), whilst the other comes with an integrated button and can be switched between "PROG" and "UART" mode.
  

Then it's a matter of choosing your programming method - you can use EsptoolEspressif's tools or (as in my case) the Arduino IDE.


Once the connections and programming was sorted (i.e. can I blink a LED!) I then used the following OTA code modified from the ESP8266 WiFi extender code:

// NAPT example released to public domain

#if LWIP_FEATURES && !LWIP_IPV6

#define HAVE_NETDUMP 0

#ifndef STASSID
#define STASSID "*****************"
#define STAPSK  "*****************"
#endif

#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>
#include <lwip/napt.h>
#include <lwip/dns.h>
#include <LwipDhcpServer.h>

const char* ssid = STASSID;
const char* password = STAPSK;
const char* host = "HostName";

#define NAPT 1000
#define NAPT_PORT 10


void setup() {
  Serial.begin(115200);
  Serial.printf("\n\nNAPT Range extender\n");
  Serial.printf("Heap on start: %d\n", ESP.getFreeHeap());

#if HAVE_NETDUMP

#include <NetDump.h>

  void dump(int netif_idx, const char* data, size_t len, int out, int success) {
    (void)success;
    Serial.print(out ? F("out ") : F(" in "));
    Serial.printf("%d ", netif_idx);

    // optional filter example: if (netDump_is_ARP(data))
    {
      netDump(Serial, data, len);
      //netDumpHex(Serial, data, len);
    }
  }
#endif

#if HAVE_NETDUMP
  phy_capture = dump;
#endif

  // first, connect to STA so we can get a proper local DNS server
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print('.');
    delay(500);
  }
  Serial.printf("\nSTA: %s (dns: %s / %s)\n",
                WiFi.localIP().toString().c_str(),
                WiFi.dnsIP(0).toString().c_str(),
                WiFi.dnsIP(1).toString().c_str());

  // give DNS servers to AP side
  dhcpSoftAP.dhcps_set_dns(0, WiFi.dnsIP(0));
  dhcpSoftAP.dhcps_set_dns(1, WiFi.dnsIP(1));

  WiFi.softAPConfig(  // enable AP, with android-compatible google domain
    IPAddress(172, 217, 28, 254),
    IPAddress(172, 217, 28, 254),
    IPAddress(255, 255, 255, 0));
  WiFi.softAP("WiFi-Mesh", STAPSK);
  Serial.printf("AP: %s\n", WiFi.softAPIP().toString().c_str());

  Serial.printf("Heap before: %d\n", ESP.getFreeHeap());
  err_t ret = ip_napt_init(NAPT, NAPT_PORT);
  Serial.printf("ip_napt_init(%d,%d): ret=%d (OK=%d)\n", NAPT, NAPT_PORT, (int)ret, (int)ERR_OK);
  if (ret == ERR_OK) {
    ret = ip_napt_enable_no(SOFTAP_IF, 1);
    Serial.printf("ip_napt_enable_no(SOFTAP_IF): ret=%d (OK=%d)\n", (int)ret, (int)ERR_OK);
    if (ret == ERR_OK) {
      Serial.printf("WiFi Network '%s' with same password is now NATed behind '%s'\n", "Charis-Mesh", STASSID);
    }
  }
  Serial.printf("Heap after napt init: %d\n", ESP.getFreeHeap());
  if (ret != ERR_OK) {
    Serial.printf("NAPT initialization failed\n");
  }
  ArduinoOTA.setHostname(host);
  ArduinoOTA.setPassword("MyPass");
  ArduinoOTA.onError([](ota_error_t error) {
    (void)error;
    ESP.restart();
  });
  /* setup the OTA server */
  ArduinoOTA.begin();
  Serial.println("Ready");

}

#else

void setup() {
  Serial.begin(115200);
  Serial.printf("\n\nNAPT not supported in this configuration\n");
}

#endif

void loop() {
  ArduinoOTA.handle();
}

The video below shows this system in a link of WiFi SSIDs stretching about 60m down the driveway as per this diagram:

I'm currently evaluating a slightly different way of putting the network "Mesh" together, but I'll save that for another video/blog.









No comments:

Post a Comment