Is there a way to get a list of SSIDs of all access points that an ESP is currently “seeing”? Similar to the list of APs in reach that are listed on my mobile?
Use case:
My BEV creates a Wifi network that I cannot use directly. But I want to detect its presence to tell that the car is in the garage (and remind us that we forgot to plug it in :).
According to the docs this sensor only exposes data of the currently connected AP. What I am looking for is a list of available (but not necessarily connected) APs.
Oh damn, I was wrong! I had seen this sensor before but misinterpreted it’s config params. But you are right @tom_l. This sensor CAN scan for available APs! Thanks.
Yepp, true. Just tested it. The scan happens on boot and whenever the ESP looses the WIFI connection.
So the hard way to rescan would be a cyclic reboot.
Unfortunately the ESP seems not to be able to scan for networks while being connected. So the moment I call the start_scanning() method the ESP logs the message Starting scan... and then disconnects. Some 20 seconds later it reconnects again and I get my new list in the sensor. I only tested this on an ESP8266. Not sure whether ESP32 could scan while holding the connection.
Overall there is not a big difference between start_scanning() and a reboot as long as you don’t use static variables or other kinds of in-memory data that would get lost on a reboot.
With this approach my task is solved. I now trigger a WIFI scan whenever the garage door closes. When the ESP reconnects it gives me the new WIFIs in range. And I can tell whether the car is now in the garage or not. Mission completed.
I may later add some testing of the signal strength (which is transmitted with the scan results) to avoid false positives when the car is parked directly in front of the garage door. In this situation the signal still gets through but is weak, which tells me that the car is not inside.
What do you see?
I have an Arduino sketch that scans for WiFi devices and the scan includes the MAC address. I can see where it would be easy to add MQTT to publish a boolean, true if present and false if not, that your Home Assistant could receive and turn into an entity.
Just a thought. The CANbus in the car should be able to tell you if the car is charging or what the state of the charge is, then an ESP device could publish that information over the ESPHome API. (Don’t ask me- I’ve never read the CANbus for any of my projects).
Thanks for your input and your ideas. The basic problem is already solved. ESPHome gives me a list of the form…
First WIFI SSID: -84db
Second WIFI SSID: -68db
Third WIFI SSID: -75db
So I can easily tell whether the car’s SSID is in reach and how strong it comes in ( => car standing in the garage or outside the door).
Now THAT is the way to do it. And I already started exactly that about half a year ago. I built a circuit based on an ESP and a CAN bus adapter, all driven by ESPHome. And it works beautifully in our conventional Renault. But not in the Aiways BEV. It’s on my task list til then to check the CAN in the Aiways with the scope and find the reason for the malfunction. Just didn’t find the time to do it. But you are very right: That approach would be the silver bullet!
Most EV’s have two OBD ports.
I haven’t found the Rosetta stone to know what I am looking for in the CAN bus, but what I am doing now is in each car, an ESP8266-01 running ESPHome that wakes every minute and tries to connect to my WiFi. If it connects, then device.status is “connected”, thus the car is home. I plan to build this into an OBD plug. The first ones are just a proof of concept.
I used a Markdown card to format the results. I call the service in an automation once every hour.
The code in the markdown card is as follows:
{%- set networks = states('sensor.esp32_wifi_scan_results').split('\n') -%}
The strongest network is {{ networks[0] }}
{{ '\n' }}
## Top 10 Networks
{{ '\n' }}
| SSID | RSSI |
|:-----|-----:|
|{%- for net in networks -%}
{% if loop.index0 < 9 %}
{%- set ssid = net.split(': ') -%}|
| {{ ssid[0] }} | {{ssid[1] }} |
{% endif %}
{%- endfor -%}
Note that I’ve split the text sensor result into a Dict array (one element per line)
And then split again at the ': " to separate the SSID name from the signal strength RSSI
And finally I’ve printed it using markdown table formatting (all the | are important)
Yes, you do this in HA. Here is the full solution for a WiFi scanner to get list of access points/SSIDs in reach of an ESP32 using ESPHome, gathered from all of the posts above:
Create a text sensor to scan the WiFi (add this to your ESP32 yaml using ESPHome)
Create an automation in Home Assistant to periodically call the service
(Add this is Home Assistant Settings → Automations & Scenes → + Create Automation
Triggers → + Add Trigger → Time pattern trigger
(I just put 5 in the Minutes section to run the automation every hour at 5 mins past)
Actions → + Add Action → Service → select the service you added in step 2
Save
(and that’s it - you can try it out by selecting the 3 dots menu at the right of the automation and hit “Run”)
Note that the ESP32 will go 'offline" for about 30 seconds while doing a scan
it reconnects to your WiFi automatically.
You can see the results by selecting the entity in Settings → Devices & Services → Entities
then put your text sensor entity name in the search field.
This shows a coloured linear graph with all the text results.
You can also see the results if you have enabled the web interface for your ESP32
by selecting Visit on the ESPHome menu in Home Assistant
For a nicer format that will show the most recent result on a dashboard in Home Assistant, add a Markdown Card.
The code in the markdown card is as follows:
{%- set networks = states('sensor.esp32_wifi_scan_results').split('\n') -%}
The strongest network is {{ networks[0] }}
{{ '\n' }}
## Top 10 Networks
{{ '\n' }}
| SSID | RSSI |
|:-----|-----:|
|{%- for net in networks -%}
{% if loop.index0 < 9 %}
{%- set ssid = net.split(': ') -%}|
| {{ ssid[0] }} | {{ssid[1] }} |
{% endif %}
{%- endfor -%}
Note that I’ve split the text sensor result into a Dict array (one element per line)
And then split again at the ': " to separate the SSID name from the signal strength RSSI
And finally I’ve printed it using markdown table formatting (all the | are important)