Micropython WoL

General discussions and questions abound development of code with MicroPython that is not hardware specific.
Target audience: MicroPython Users.
Strimis10
Posts: 7
Joined: Sun Jul 10, 2022 4:13 pm

Micropython WoL

Post by Strimis10 » Sun Jul 10, 2022 6:27 pm

Hello hello, I'm in the middle of this project where I use an esp01 running micropython (1MB version) to host a website on my local network so that I can send WoL packages to my file server. I have the code working on my pc (python 3.7).

So because I was too lazy to figure out how to build a magic packet I just yoinked the code from https://pypi.org/project/wakeonlan/
and modified it a little (mostly removed what I didn't need) and just ran that and it worked!, but now I copy pasted the code to my esp01, I had to modify some stuff and now I have an error where it throws an error;
"AttributeError: 'module' object has no attribute 'SO_BROADCAST'" it uses socket btw...

Here is the code I run in micropython:

Code: Select all

import socket
import ubinascii


BROADCAST_IP = "192.168.0.61"


DEFAULT_PORT = 9

 
def create_magic_packet(macaddress: str) -> bytes:

    if len(macaddress) == 17:
        sep = macaddress[2]
        macaddress = macaddress.replace(sep, "")
    elif len(macaddress) != 12:
        raise ValueError("Incorrect MAC address format")

    return ubinascii.unhexlify("F" * 12 + macaddress * 16)


def send_magic_packet(
    *macs: str,
    ip_address: str = BROADCAST_IP,
    port: int = DEFAULT_PORT,
    interface: str = None
) -> None:  

    packets = [create_magic_packet(mac) for mac in macs]
    print("aaa")
    
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    if interface is not None:
        sock.bind((interface, 0))
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
    sock.connect((ip_address, port))
    for packet in packets: 
        sock.send(packet) 
    sock.close()
    
    
    print("sent")
    
    



And here's the code I run on my pc:

import socket



BROADCAST_IP = "192.168.0.61"
DEFAULT_PORT = 9


def create_magic_packet(macaddress: str) -> bytes:
    """
    Create a magic packet.
    A magic packet is a packet that can be used with the for wake on lan
    protocol to wake up a computer. The packet is constructed from the
    mac address given as a parameter.
    Args:
        macaddress: the mac address that should be parsed into a magic packet.
    """
    if len(macaddress) == 17:
        sep = macaddress[2]
        macaddress = macaddress.replace(sep, "")
    elif len(macaddress) != 12:
        raise ValueError("Incorrect MAC address format")

    return bytes.fromhex("F" * 12 + macaddress * 16)


def send_magic_packet(
    *macs: str,
    ip_address: str = BROADCAST_IP,
    port: int = DEFAULT_PORT,
    interface: str = None
) -> None:
    """
    Wake up computers having any of the given mac addresses.
    Wake on lan must be enabled on the host device.
    Args:
        macs: One or more macaddresses of machines to wake.
    Keyword Args:
        ip_address: the ip address of the host to send the magic packet to.
        port: the port of the host to send the magic packet to.
        interface: the ip address of the network adapter to route the magic packet through.
    """
    packets = [create_magic_packet(mac) for mac in macs]

    with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as sock:
        if interface is not None:
            sock.bind((interface, 0))
        sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
        sock.connect((ip_address, port))
        for packet in packets:
            sock.send(packet)


send_magic_packet("bc:5f:f4:91:ed:14") 

As you might see I don't use the broadcast ip, that's because I can't find it... :[



any help is greatly appreciated :)


I had a hard time figuring out what my broadcast ip was but I found this really good video on YouTube explaining how to get it: https://www.youtube.com/watch?v=1pZNjRZLNqI
Last edited by Strimis10 on Wed Nov 09, 2022 6:10 pm, edited 2 times in total.

User avatar
jimmo
Posts: 2754
Joined: Tue Aug 08, 2017 1:57 am
Location: Sydney, Australia
Contact:

Re: Micropython WoL

Post by jimmo » Mon Jul 11, 2022 1:09 am

Strimis10 wrote:
Sun Jul 10, 2022 6:27 pm
"AttributeError: 'module' object has no attribute 'SO_BROADCAST'" it uses socket btw...
I don't know why we don't make this constant available in Python (probably to save space) but the value is 0x20, so you can just define it yourself.

Code: Select all

SOF_BROADCAST = const(0x20)

Strimis10
Posts: 7
Joined: Sun Jul 10, 2022 4:13 pm

Re: Micropython WoL

Post by Strimis10 » Mon Jul 11, 2022 7:59 am

I don't really understand, what I should do with that? should I replace "socket.SO_BROADCAST" with "SOF_BROADCAST = const(0x20)"?

User avatar
jimmo
Posts: 2754
Joined: Tue Aug 08, 2017 1:57 am
Location: Sydney, Australia
Contact:

Re: Micropython WoL

Post by jimmo » Mon Jul 11, 2022 8:58 am

Strimis10 wrote:
Mon Jul 11, 2022 7:59 am
I don't really understand, what I should do with that? should I replace "socket.SO_BROADCAST" with "SOF_BROADCAST = const(0x20)"?
You should replace socket.SO_BROADCAST with SOF_BROADCAST

and put the constant definition at the top of the file somewhere

Strimis10
Posts: 7
Joined: Sun Jul 10, 2022 4:13 pm

Re: Micropython WoL

Post by Strimis10 » Mon Jul 11, 2022 3:54 pm

Okay, so I did that and the script completes but it prints "Warning: lwip.setsockopt() not implemented". I can see the packet in wireshark if I send it to my pc but it won't start the server

User avatar
jimmo
Posts: 2754
Joined: Tue Aug 08, 2017 1:57 am
Location: Sydney, Australia
Contact:

Re: Micropython WoL

Post by jimmo » Mon Jul 11, 2022 4:20 pm

Strimis10 wrote:
Mon Jul 11, 2022 3:54 pm
Okay, so I did that and the script completes but it prints "Warning: lwip.setsockopt() not implemented". I can see the packet in wireshark if I send it to my pc but it won't start the server
Looks like it would need to be added here:
https://github.com/micropython/micropyt ... ip.c#L1365

I guess that's why the constant wasn't available on the module. I guess duplicate the implementation for SOF_REUSEADDR?

I'm fairly sure the underlying LWIP does support this.

Strimis10
Posts: 7
Joined: Sun Jul 10, 2022 4:13 pm

Re: Micropython WoL

Post by Strimis10 » Mon Jul 11, 2022 6:09 pm

what was I supposed to do?

User avatar
jimmo
Posts: 2754
Joined: Tue Aug 08, 2017 1:57 am
Location: Sydney, Australia
Contact:

Re: Micropython WoL

Post by jimmo » Tue Jul 12, 2022 11:44 am

Strimis10 wrote:
Mon Jul 11, 2022 6:09 pm
what was I supposed to do?
If you wanted to try fixing the MicroPython LWIP bindings to add support for SOF_BROADCAST, that would be where to do it.

Strimis10
Posts: 7
Joined: Sun Jul 10, 2022 4:13 pm

Re: Micropython WoL

Post by Strimis10 » Tue Jul 12, 2022 3:42 pm

sorry, but how?, just copy paste it into the file?

Strimis10
Posts: 7
Joined: Sun Jul 10, 2022 4:13 pm

Re: Micropython WoL

Post by Strimis10 » Tue Jul 12, 2022 9:27 pm

Okay, sorry. I fixed it, after you helped me with the broadcast thing all I had to do was to send the packet to the broadcast ip, I had a hard time figuring out what my broadcast ip was but I found this really good video on YouTube explaining how to get it: https://www.youtube.com/watch?v=1pZNjRZLNqI

Thanks alot :D

Post Reply