Konubinix' opinionated web of thoughts

How to Play With Espnow Between an Esp8266/Micropython and Linux

Fleeting

how to play with espnow in a esp8266 with micropython

on the server

VERSION 0.8

IMPORT github.com/Konubinix/Earthfile AS e

espnow-src:
    FROM alpine
    WORKDIR /app
    GIT CLONE https://github.com/ChuckMash/ESPythoNOW /app
    SAVE ARTIFACT /app

espnow-build:
    FROM e+alpine --extra_packages="ipython wireless-tools libpcap"
    WORKDIR /app
    COPY +espnow-src/app /app
    DO e+PYTHON_VENV --base /app --packages "scapy==2.5.0"

espnow:
    FROM +espnow-build
    SAVE IMAGE espnow

earthly +espnow

Start with docker run --privileged --network=host espnow

First, run ./prep.sh <interface> <channel> to put make the interface listen to the proper channel. I used ./prep.sh wlp2s0 4 in my setup.

then, run scapy and try

import sys
sys.path.append(".")
from ESPythoNOW import *
import time

def callback(from_mac, to_mac, msg):
    print("ESP-NOW message from %s to %s: %s" % (from_mac, to_mac, msg))

espnow = ESPythoNow(interface="wlp2s0", callback=callback)
espnow.start()
bytes.fromhex(espnow.local_hw_mac.replace(':', ''))

This will output the mac address to give to the board. Mine was b'|\\\xf8\xb3\xe0R'.

on the board

mpremote, then

import espnow
import network

ap = network.WLAN(network.WLAN.IF_AP)
ap.active(True)
ap.config(channel=4)

e = espnow.ESPNow()
e.active(True)
peer = b'|\\\xf8\xb3\xe0R'
e.add_peer(peer)

ap.config("mac")

It will connect to the computer and output the mac address of the board, mine was b'^\xcf\x7f\x0e\xe1\x19'

from the computer to the board

To receive data from the board, simply run

e.recv()

And from the scapy session in the computer

espnow.send(':'.join(format(x, '02x') for x in b'\\\xcf\x7f\x0e\xe1\x19'), b"Hello from the computer")

You should see it in the board.

from the board to the computer

The computer already listens to messages, using the callback in the code above.

In the board, run

e.send(b'|\\\xf8\xb3\xe0R', b'Hello from the board')

You should see it appear in the computer.

using aioespnow

mpremote mip install aioespnow

Adapting the example given in https://github.com/micropython/micropython-lib/tree/master/micropython/aioespnow

Also, using aiorepl (mpremote mip install aioespnow)

import network
import aioespnow
import asyncio
import aiorepl

sta = network.WLAN(network.WLAN.IF_STA)
sta.active(True)
# ap = network.WLAN(network.WLAN.IF_AP)
# ap.active(True)
# ap.config(channel=4)

e = aioespnow.AIOESPNow()
e.active(True)
peer = b'|\\\xf8\xb3\xe0R'
e.add_peer(peer)

# Send a periodic ping to a peer
async def heartbeat(e, peer, period=30):
    while True:
        if not await e.asend(peer, b'ping'):
            print("Heartbeat: peer not responding:", peer)
        else:
            print("Heartbeat: ping", peer)
        await asyncio.sleep(period)

# Echo any received messages back to the sender
async def echo_server(e):
    async for mac, msg in e:
        print("Echo:", msg)
        try:
            await e.asend(mac, msg)
        except OSError as err:
            if len(err.args) > 1 and err.args[1] == 'ESP_ERR_ESPNOW_NOT_FOUND':
                e.add_peer(mac)
                await e.asend(mac, msg)

async def main(e, peer, timeout, period):
    asyncio.create_task(heartbeat(e, peer, period))
    asyncio.create_task(echo_server(e))
    asyncio.create_task(aiorepl.task())
    await asyncio.sleep(timeout)

asyncio.run(main(e, peer, 120, 10))