Closed PaulskPt closed 8 months ago
Any news about this topic?
We have https://github.com/adafruit/circuitpython/pull/8752 and https://github.com/adafruit/circuitpython/pull/8306. Do these help? You can test the 9.0.0-alpha releases.
Thank you Dan. I am going to test it.
Monday, January 22, 2024. 1h38 PM GMT
Board: Adafruit Feather ESP32-S2 TFT Flashed with: Adafruit CircuitPython 9.0.0-alpha.6-29-g5f318c37bb on 2024-01-19; Adafruit Feather ESP32-S2 TFT with ESP32S2
IDE: Mu 1.2.0
The REPL output below shows that the board, connected to the in house WiFi, receives the UPD multicast data packets that X-Plane 12 was set for to transmit.
a) REPL output of manual test to see which attributes socketpool.SocketPool has now (with the latest version of CircuitPython):
Adafruit CircuitPython 9.0.0-alpha.6-29-g5f318c37bb on 2024-01-19; Adafruit Feather ESP32-S2 TFT with ESP32S2
>>>
>>> import wifi
>>> import socketpool
>>> pl = socketpool.SocketPool(wifi.radio)
>>> dir(pl)
['__class__', 'AF_INET', 'AF_INET6', 'EAI_NONAME', 'IPPROTO_ICMP', 'IPPROTO_IP', 'IPPROTO_IPV6', 'IPPROTO_RAW', 'IPPROTO_TCP', 'IPPROTO_UDP', 'IP_MULTICAST_TTL', 'SOCK_DGRAM', 'SOCK_RAW', 'SOCK_STREAM', 'TCP_NODELAY', 'gaierror', 'getaddrinfo', 'socket']
>>>
b) REPL output (cpy script running):
soft reboot
Auto-reload is on. Simply save files over USB to run them or enter REPL to disable.
code.py output:
This script is running on an 'adafruit_feather_esp32s2_tft'
main(): Date time sync interval set to: 10 minutes
dg.__init__(): Entering...
dr.__init__(): self.use_udp_host= True
dr.__init__(): self.MCAST_GRP= 235.255.1.1
dr.__init__(): self.MCAST_PORT= 49707
setup(): WiFi already connected to: 'xxxxxx' (Note: SSID masked)
create_groups(): loading image 'bmp/avatar.bmp'
create_groups(): loading image 'bmp/blinka.bmp'
main(): We are running Python version: 3.4.0
main(): The following values will be used:
main(): <IP-address> of this device: 192.168.1.xxx (Note: IP masked)
main(): and <Multicast Port>: 49707
-----------------------------------------------------------------------------------------
wifi_connect(): Connecting to 'xxxxx' (Note: SSID masked)
wifi_connect(): WiFi already connected and IP is wanted IP: 192.168.1.xxx (Note: IP masked)
wifi_connect(): connected to: 'xxxxx' (Note: SSID masked)
wifi_connect(): Resolved google address: '216.58.209.78'
wifi_connect(): Ping google.com [216.58.209.78]:18 ms
main(): We are going to run a dataref test...
main(): type(dr)= <class 'XPlaneDatarefRx'>
main(): contents dr= <XPlaneDatarefRx object at 0x3f804670>
dr.OpenDatarefSocket: We are going to open a socket for Dataref request and answers
dr.OpenDatarefSocket: type(pool)= <class 'SocketPool'>
dr.FindIp(): type(self.BeaconData)= <class 'dict'>
dr.FindIp(): self.BeaconData= {}
dr.FindIp(): packet_size= 71
dr.FindIp(): waiting for beacon packets, udp_host 192.168.1.xxx, port 49707 (Note: IP masked)
dr.FindIp(): header= DATA
dr.FindIp(): nr bytes received= 71 from 192.168.1.xxx (Note: IP of host running XPlane12 masked)
dr.dataref_test(): beacon: {}
main(): call to dr.dataref_test() sucdessful
dg.OpenUDPSocket(): pool= <SocketPool>
dg.OpenUDPSocket(): waiting for packets on host 192.168.1.xxx, port 49707 (Note: IP masked)
dg.msgs_unpack(): using unpack string: 'self.udp_unpack_str_3', size= 36 bytes, value= '<iffffifff'
dg.msgs_unpack(): us= (3, 101.651, 101.951, 104.995, 104.995, -998653952, 116.978, 120.826, 120.826)
dg.msgs_unpack(): self.values_struct_3.items() = dict_items([('vtrue_ktgs', 104.995), ('vind_mph', 116.978), ('vtrue_mphas', 120.826), ('vtrue_mphgs', 120.826), ('ID', 3), ('vind_keas', 101.951), ('vtrue_ktas', 104.995), ('vind_kias', 101.651), ('nothing', -998653952)])
dg.msgs_unpack(): using unpack string: 'self.udp_unpack_str_17', size= 36 bytes, value= '<ifffiffif'
dg.msgs_unpack(): us= (17, 1.7446, 1.91166, 273.543, -998653952, 273.255, -0.288664, -998653952, 276.984)
dg.msgs_unpack(): self.values_struct_17.items() = dict_items([('mag_comp', 276.984), ('hding_mag', 273.255), ('mavar_deg', -0.288664), ('hding_true', 273.543), ('ID', 17), ('nothing1', -998653952), ('pitch_deg', 1.7446), ('roll_deg', 1.91166), ('nothing2', -998653952)])
dg.msgs_unpack(): using unpack string: 'self.udp_unpack_str_20', size= 36 bytes, value= '<iffffffff'
dg.msgs_unpack(): us= (20, 51.5768, -1.61574, 1997.41, 1648.58, 344.963, 1997.41, 51.5, -1.0)
dg.msgs_unpack(): self.values_struct_20.items() = dict_items([('terrn_ftmsl', 344.963), ('lat_orign', 51.5), ('lon_deg', -1.61574), ('lon_orign', -1.0), ('ID', 20), ('p-alt_ftmsl', 1997.41), ('CG_ftmsl', 1997.41), ('lat_deg', 51.5768), ('gear_ftagl', 1648.58)])
dg.msgs_unpack(): using unpack string: 'self.udp_unpack_str_102', size= 36 bytes, value= '<iffffffii'
dg.msgs_unpack(): us= (102, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, 1177464832)
dg.msgs_unpack(): self.values_struct_102.items() = dict_items([('dme_speed', 0.0), ('dme_mode', 0.0), ('dme_time', 0.0), ('dme_found', 0.0), ('ID', 102), ('dme_n-typ', 0), ('dme_nav01', 0.0), ('dme-3_freq', 1177464832), ('dme_dist', 0.0)])
dg.disp_hdg_alt(): xp_lst= [(3, 101.651, 101.951, 104.995, 104.995, -998653952, 116.978, 120.826, 120.826), (17, 1.7446, 1.91166, 273.543, -998653952, 273.255, -0.288664, -998653952, 276.984), (20, 51.5768, -1.61574, 1997.41, 1648.58, 344.963, 1997.41, 51.5, -1.0), (102, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, 1177464832)]
dg.disp_hdg_alt(): self.hdg_alt_lst= [273.255, 1997.41]
dg.disp_hdg_alt(): showing page: main
main(): call to dg.datagram_test() successful
[...] etcetera...
Conclusion: problem solved for me within this context. To everyone that contributed to add the requested attributes my sincere "Thank you!".
Closing this issue
Monday, January 22, 2024. 1h38 PM GMT
Board: Adafruit Feather ESP32-S2 TFT Flashed with: Adafruit CircuitPython 9.0.0-alpha.6-29-g5f318c37bb on 2024-01-19; Adafruit Feather ESP32-S2 TFT with ESP32S2
IDE: Mu 1.2.0
The REPL output below shows that the board, connected to the in house WiFi, receives the UPD multicast data packets that X-Plane 12 was set for to transmit.
a) REPL output of manual test to see which attributes socketpool.SocketPool has now (with the latest version of CircuitPython):
Adafruit CircuitPython 9.0.0-alpha.6-29-g5f318c37bb on 2024-01-19; Adafruit Feather ESP32-S2 TFT with ESP32S2
>>> >>> import wifi >>> import socketpool >>> pl = socketpool.SocketPool(wifi.radio) >>> dir(pl) ['__class__', 'AF_INET', 'AF_INET6', 'EAI_NONAME', 'IPPROTO_ICMP', 'IPPROTO_IP', 'IPPROTO_IPV6', 'IPPROTO_RAW', 'IPPROTO_TCP', 'IPPROTO_UDP', 'IP_MULTICAST_TTL', 'SOCK_DGRAM', 'SOCK_RAW', 'SOCK_STREAM', 'TCP_NODELAY', 'gaierror', 'getaddrinfo', 'socket'] >>>
b) REPL output (cpy script running):
soft reboot Auto-reload is on. Simply save files over USB to run them or enter REPL to disable. code.py output: This script is running on an 'adafruit_feather_esp32s2_tft' main(): Date time sync interval set to: 10 minutes dg.__init__(): Entering... dr.__init__(): self.use_udp_host= True dr.__init__(): self.MCAST_GRP= 235.255.1.1 dr.__init__(): self.MCAST_PORT= 49707 setup(): WiFi already connected to: 'xxxxxx' (Note: SSID masked) create_groups(): loading image 'bmp/avatar.bmp' create_groups(): loading image 'bmp/blinka.bmp' main(): We are running Python version: 3.4.0 main(): The following values will be used: main(): <IP-address> of this device: 192.168.1.xxx (Note: IP masked) main(): and <Multicast Port>: 49707 ----------------------------------------------------------------------------------------- wifi_connect(): Connecting to 'xxxxx' (Note: SSID masked) wifi_connect(): WiFi already connected and IP is wanted IP: 192.168.1.xxx (Note: IP masked) wifi_connect(): connected to: 'xxxxx' (Note: SSID masked) wifi_connect(): Resolved google address: '216.58.209.78' wifi_connect(): Ping google.com [216.58.209.78]:18 ms main(): We are going to run a dataref test... main(): type(dr)= <class 'XPlaneDatarefRx'> main(): contents dr= <XPlaneDatarefRx object at 0x3f804670> dr.OpenDatarefSocket: We are going to open a socket for Dataref request and answers dr.OpenDatarefSocket: type(pool)= <class 'SocketPool'> dr.FindIp(): type(self.BeaconData)= <class 'dict'> dr.FindIp(): self.BeaconData= {} dr.FindIp(): packet_size= 71 dr.FindIp(): waiting for beacon packets, udp_host 192.168.1.xxx, port 49707 (Note: IP masked) dr.FindIp(): header= DATA dr.FindIp(): nr bytes received= 71 from 192.168.1.xxx (Note: IP of host running XPlane12 masked) dr.dataref_test(): beacon: {} main(): call to dr.dataref_test() sucdessful dg.OpenUDPSocket(): pool= <SocketPool> dg.OpenUDPSocket(): waiting for packets on host 192.168.1.xxx, port 49707 (Note: IP masked) dg.msgs_unpack(): using unpack string: 'self.udp_unpack_str_3', size= 36 bytes, value= '<iffffifff' dg.msgs_unpack(): us= (3, 101.651, 101.951, 104.995, 104.995, -998653952, 116.978, 120.826, 120.826) dg.msgs_unpack(): self.values_struct_3.items() = dict_items([('vtrue_ktgs', 104.995), ('vind_mph', 116.978), ('vtrue_mphas', 120.826), ('vtrue_mphgs', 120.826), ('ID', 3), ('vind_keas', 101.951), ('vtrue_ktas', 104.995), ('vind_kias', 101.651), ('nothing', -998653952)]) dg.msgs_unpack(): using unpack string: 'self.udp_unpack_str_17', size= 36 bytes, value= '<ifffiffif' dg.msgs_unpack(): us= (17, 1.7446, 1.91166, 273.543, -998653952, 273.255, -0.288664, -998653952, 276.984) dg.msgs_unpack(): self.values_struct_17.items() = dict_items([('mag_comp', 276.984), ('hding_mag', 273.255), ('mavar_deg', -0.288664), ('hding_true', 273.543), ('ID', 17), ('nothing1', -998653952), ('pitch_deg', 1.7446), ('roll_deg', 1.91166), ('nothing2', -998653952)]) dg.msgs_unpack(): using unpack string: 'self.udp_unpack_str_20', size= 36 bytes, value= '<iffffffff' dg.msgs_unpack(): us= (20, 51.5768, -1.61574, 1997.41, 1648.58, 344.963, 1997.41, 51.5, -1.0) dg.msgs_unpack(): self.values_struct_20.items() = dict_items([('terrn_ftmsl', 344.963), ('lat_orign', 51.5), ('lon_deg', -1.61574), ('lon_orign', -1.0), ('ID', 20), ('p-alt_ftmsl', 1997.41), ('CG_ftmsl', 1997.41), ('lat_deg', 51.5768), ('gear_ftagl', 1648.58)]) dg.msgs_unpack(): using unpack string: 'self.udp_unpack_str_102', size= 36 bytes, value= '<iffffffii' dg.msgs_unpack(): us= (102, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, 1177464832) dg.msgs_unpack(): self.values_struct_102.items() = dict_items([('dme_speed', 0.0), ('dme_mode', 0.0), ('dme_time', 0.0), ('dme_found', 0.0), ('ID', 102), ('dme_n-typ', 0), ('dme_nav01', 0.0), ('dme-3_freq', 1177464832), ('dme_dist', 0.0)]) dg.disp_hdg_alt(): xp_lst= [(3, 101.651, 101.951, 104.995, 104.995, -998653952, 116.978, 120.826, 120.826), (17, 1.7446, 1.91166, 273.543, -998653952, 273.255, -0.288664, -998653952, 276.984), (20, 51.5768, -1.61574, 1997.41, 1648.58, 344.963, 1997.41, 51.5, -1.0), (102, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, 1177464832)] dg.disp_hdg_alt(): self.hdg_alt_lst= [273.255, 1997.41] dg.disp_hdg_alt(): showing page: main main(): call to dg.datagram_test() successful [...] etcetera...
Conclusion: problem solved for me within this context. To everyone that contributed to add the requested attributes my sincere "Thank you!".
Hi @PaulskPt , Would you mind to provide part of code to show how to receive multicast udp msg? I'm have problem too to receive multicast udp message. and cannot figure out how to make it work in circuitpython. I'm using 9.0.0 beta0
Hi @zenz , thank you for your request. I published/renewed my repo on Github. Here is the link: repo . Let me know if you need more assistance. Don't forget to fill in the blanks in file ´settings.toml
.
I had an issue with the repo. I deleted it and created a new one. I pasted the new link in my first answer to you above. I tested the link. It works. Try again please.
I had an issue with the repo. I deleted it and created a new one. I pasted the new link in my first answer to you above. I tested the link. It works. Try again please.
Still no luck. perhaps you'd make it private? I can't see it with 404 error.
I am so sorry, yes the repo was labled private. I don't understand it because I use Github for Desktop (MS Windows 11) PC, created the repo and clicked to publicize it. Try again please
I am so sorry, yes the repo was labled private. I don't understand it because I use Github for Desktop (MS Windows 11) PC, created the repo and clicked to publicize it. Try again please
Thank you, I can see it now. but from your code, I think you actually use unicast, not multicast?
I'm trying this out:
So far, one of my printers sends packets to 239.255.1.1:138. Suggestions welcome if I have some of the protocol snippets wrong.
Years ago when I started the project, it used MULTICAST_GROUP and MULTICAST PORT (in this moment these values are still in the file settings.toml and read in at start). In the past I used SBC (Raspberry Pi or similar equipment) and later microcontrollers. These were connected to a desktop PC running X-Plane (10 it was) via USB-cable and a USB-to-Serial converter, receiving serial data via UART. The current state of the app, using data from XPlane-12 which the flightsimulator transmits to a device with the chosen IP-address. I use this method now so my ESP32-S2 TFT now will be able to run this Circuitpython application using WiFi and only be powered from a battery.
I'm trying this out:
code.py
import os import asyncio import traceback import wifi import socketpool import time import traceback # choose your own multicast group adventure GROUPS = (("239.255.255.250", 1900), ("224.0.0.251", 5353), ("239.255.1.1", 138)) MAXBUF = 256 TIMEOUT = 0 # non-blocking async def udpserver(group): with pool.socket(pool.AF_INET, pool.SOCK_DGRAM, pool.IP_MULTICAST_TTL) as s: s.bind((group[0], group[1])) s.settimeout(TIMEOUT) buf = bytearray(MAXBUF) print(f'{time.monotonic_ns()} Listening on {group[0]}:{group[1]}') while True: try: size, sender = s.recvfrom_into(buf) print(f'{time.monotonic_ns()} Received UDP packet from {sender[0]}:{sender[1]} on {group[0]}:{group[1]}', buf[0:size]) except OSError as ex: # if ex.errno == 11: # EAGAIN pass else: print(f'{group[0]}:{group[1]} {repr(ex)}') traceback.print_exception(ex, ex, ex.__traceback__) await asyncio.sleep(0) time.sleep(3) # wait for serial pool = socketpool.SocketPool(wifi.radio) # choose your own connect adventure wifi.radio.connect(os.getenv("WIFI_SSID"), os.getenv("WIFI_PASSWORD")) print(wifi.radio.ipv4_address) async def main(): tasks = [] for taskno in range(len(GROUPS)): tasks.append(asyncio.create_task(udpserver(GROUPS[taskno]))) await asyncio.gather(*tasks) asyncio.run(main())
So far, one of my printers sends packets to 239.255.1.1:138. Suggestions welcome if I have some of the protocol snippets wrong.
I have similar code, it can run, but can receive nothing(my code written with arduino works). so I think multicast doesn't work.
Some years ago I wrote and used successfully a Python script for a Raspberry Pi to receive, unpack and display UDP multicast packets, broadcasted from an X-Plane flight simulator app running on a MS Windows PC. In this moment I am trying to port this script to CircuitPython V8.0.0.-rc.2 on an Adafruit Feather ESP32-S2 with TFT, however I am not able to proceed because, TMHO, the core module 'socketpool' lacks attributes I need for my project.
Ref: readthedocs_latest_socketpool socketpool has (among some others) the following attributes: 'AF_INET', 'AF_INET6', 'EAI_NONAME', 'IPPROTO_TCP', 'SOCK_DGRAM', 'SOCK_RAW', 'SOCK_STREAM', 'TCP_NODELAY', 'gaierror', 'getaddrinfo', 'socket'
My 'wishlist' of attributes to add: IPPROTO_UDP SO_REUSEADDR SOL_SOCKET IPPROTO_IP IP_ADD_MEMBERSHIP INADDR_ANY inet_aton()
Below an image of BECN packets captured using WireShark: multicast_udp_packets_captured
The following is a test script to receive, unpack and print to REPL received multicast udp packets. It fails because of socketpool.SocketPool is lacking the attributes listed above in my 'wishlist':