Setting static IP of ESP32 using esphome based on a stored value

I am trying to set the static IP address of an ESP32 in YAML programmatically. Meaning I have a global like this:

globals:
  - id: my_ip
    type: int
    restore_value: true
    initial_value: '230'

and I want to set the END of 192.168.1.END to 230 which will make the static IP address 192.168.1.230.

I have tried

manual_ip:
    static_ip: 
    - lambda: auto static_ip = esphome::network::IPAddress(192, 168, 1, id(my_ip));

I have also tried lambda in esphome:on_boot with functions from the WiFi component such as

set_manual_ip(manual_ip(192, 168, 1, id(my_ip))

to no success because it cannot find set_manual_ip as part of the esphome::network even though it is in the header file.

Is there any way of doing what I am trying to do? I cannot find many answers on this through google. Thanks.

From the ESPHome documentation: WiFi Component - ESPHome - Smart Home Made Simple will show you the current syntax and options. This will possibly be referenced by any AI engines you care to beg for help, but better go to the source that is up to date and correct.

Your router DHCP configuration may also need to be updated to reserve a Static IP Address to match so no other device is allocated the IP Address. Again, your router manual will be the definitive source of the correct procedures to follow. Check the vendor website first, then your ISP if they have supplied the router.

1 Like

Are you just trying to set a static IP address, or are you trying to change the ESP's address while it is running ?

I have allocated DHCP addresses at the router, and want a simple way to use a common file for the actual wifi: yaml code. I found that setting a substitution in each device's yaml to the last octet of the IP address (what you called END) allowed me to then call a common wifi.yaml file.

In the yaml for each device

substitutions:
  deviceIP: 230                        # last octet of static IP address

packages:
  common_wifi: !include _common_wifi.yaml

and in file _common_wifi.yaml

wifi:
  ssid:     !secret wifi_ssid
  password: !secret wifi_password
  manual_ip:
    static_ip: 192.168.1.${deviceIP}
    gateway: 192.168.1.1
    subnet: 255.255.255.0
  fast_connect: True
1 Like

I am trying to set the static IP and want to be able to change it on the ESP32 using a button so that on next boot it uses the new static IP address instead.

Currently I have tried the following too:


globals:
  - id: my_ip
    type: int
    restore_value: true
    initial_value: '230'

substitutions:
  get_end_num: 
    - lambda: |-
        return id(my_ip);
  static_ip: 192.168.1.${get_end_num}

wifi:
  networks:
    - ssid: anSSID
      password: aPassword
  manual_ip:
    static_ip: $static_ip

I have tried a combination of above including using return id(my_ip).c_str(); but not successfuly so far. I get an error during compile time saying " 192.168.1.[{'lambda': 'return id(my_ip);'}] is not a valid IPv4 address." I think it has to do with IP being a specific type (i.e. not string or integar) but when I tried to create this type of variable using esphome::network::IPAddress(192, 168, 1, id(my_ip)); that also did not work.

Yes that is a very different problem. I believe substitutions are done at compile time, so not very helpful for you.

I think it might come down to the order things are executed during boot - complicated by ESPHome being multi-threaded.
The global variable value is already in memory - but your code to extract it will have to run to assemble the IP address before the thread which initialises the wi-fi connection.

I haven't tried this myself ... but I'm guessing you will want to set wifi: enable_on_boot: false; and immediately after extracting the global variable and set the IP Address field, then execute the wifi.enable action. Unfortunately I'm not experienced with C or ESPHome internals to suggest how to set the IP Address ... probably best to ask on the ESPHome discord.

By connecting to the ESP32's serial port (usually connecting the ESP32's USB socket to your PC) you can view the log while it is booting up - which will be massively helpful while trying to get this working.

May I ask why you need to change the IP after a reboot?

I use a common "connections.yaml" include file and used to set the manual_ip for each device based on what I configured in my DHCP reservations. Maybe a year ago I removed all that and just let DHCP hand out the IPs. Maybe that takes a tiny bit more time when the ESP boots, but haven't noticed any difference.

(I main reason I removed the IPs from the ESP configs is because I'm planning on changing the subnet address.)

There's one argument one might want to change the IP of a device which is reorganization of devices, so that their IPs are within a wanted region, lets assume all ESP deviced should be from within IP ...10 till ...30
This is normally done by having the lines (example) in your wifi.yaml (beside other lines required)

wifi:
  manual_ip:
    static_ip: 192.168.1.10
  use_address: 192.168.1.5

what'll happen is the device will be know on ip ...10 after it got OTA flashed and rebooted
but the OTA flash was carried out on the device which was know to be available on ip ...5

but be warned, the culprit is, you need to carry out another OTA flash, this time with a modfied wifi section in the form

wifi:
  manual_ip:
    static_ip: 192.168.1.10
  # use_address: 192.168.1.5

since if you don't, any futher OTA flash would again try to flash to IP ....5 which at worst was taken by another ESP device inbetween which then accepts that OTA flash attempt, resulting in 2 devices having the same new IP ....10 means you're network is in trouble.

All the rest, using 'substitutions' or even 'vars' being passed to an !included wifi.yaml works to not hardcode an IP into a wifi.yaml

Can I offer another path to success? The ESP32 MAC Address (allocated at chip manufacture time) does not change, irrespective of the IP Address. In your router DHCP configuration, allocate a fixed IP Address you want for the ESP32, and when it next asks for a connection, it will get the one you have chosen for it. Want to change the ESP32 IP Address to another? Change it on the router, save and reboot the router, and when the connection comes back up again, voila!

Hand reconfiguration required on the router, but still not sure why you want to chop and change the IP Address programmatically. Even the docs recommend setting a fixed address. Care to be a bit more specific in your use case? What is your end goal?

You don't have to hard code it as a manual IP Address in ESPHome - see the docs, it says optional.

Also, does use_address option work for a second IP Address? Do you just want two, or do you want to go with more? You may have to code custom firmware, and have the non-ESPHome code disconnect before reconnecting with new parameters.

For AP perhaps?