src/eric7/MicroPython/Devices/RP2040Devices.py

branch
mpy_network
changeset 9787
163511257f24
parent 9782
67414f28db68
child 9788
12294115900a
equal deleted inserted replaced
9783:5f84d5eeee9e 9787:163511257f24
9 """ 9 """
10 10
11 import ast 11 import ast
12 import binascii 12 import binascii
13 import json 13 import json
14 import os
14 15
15 from PyQt6.QtCore import QUrl, pyqtSlot 16 from PyQt6.QtCore import QUrl, pyqtSlot
16 from PyQt6.QtNetwork import QNetworkRequest 17 from PyQt6.QtNetwork import QNetworkRequest
17 from PyQt6.QtWidgets import QDialog, QMenu 18 from PyQt6.QtWidgets import QDialog, QMenu
18 19
504 @rtype tuple of (bool, str) 505 @rtype tuple of (bool, str)
505 """ 506 """
506 if self._deviceData["wifi_type"] == "picow": 507 if self._deviceData["wifi_type"] == "picow":
507 country = Preferences.getMicroPython("WifiCountry").upper() 508 country = Preferences.getMicroPython("WifiCountry").upper()
508 command = """ 509 command = """
509 def connect_wifi(ssid, password): 510 def connect_wifi(ssid, password, country):
510 import network 511 import network
511 import rp2 512 import rp2
512 import ujson 513 import ujson
513 from time import sleep 514 from time import sleep
514 515
515 rp2.country({2}) 516 rp2.country(country)
516 517
517 wifi = network.WLAN(network.STA_IF) 518 wifi = network.WLAN(network.STA_IF)
518 wifi.active(False) 519 wifi.active(False)
519 wifi.active(True) 520 wifi.active(True)
520 wifi.connect(ssid, password) 521 wifi.connect(ssid, password)
525 max_wait -= 1 526 max_wait -= 1
526 sleep(0.1) 527 sleep(0.1)
527 status = wifi.status() 528 status = wifi.status()
528 print(ujson.dumps({{'connected': wifi.isconnected(), 'status': status}})) 529 print(ujson.dumps({{'connected': wifi.isconnected(), 'status': status}}))
529 530
530 connect_wifi({0}, {1}) 531 connect_wifi({0}, {1}, {2})
531 del connect_wifi 532 del connect_wifi
532 """.format( 533 """.format(
533 repr(ssid), 534 repr(ssid),
534 repr(password if password else ""), 535 repr(password if password else ""),
535 repr(country if country else "XX"), 536 repr(country if country else "XX"),
589 out, err = self._interface.execute(command) 590 out, err = self._interface.execute(command)
590 if err: 591 if err:
591 return False, err 592 return False, err
592 593
593 return out.decode("utf-8").strip() == "True", "" 594 return out.decode("utf-8").strip() == "True", ""
595
596 def writeCredentials(self, ssid, password):
597 """
598 Public method to write the given credentials to the connected device and modify
599 the start script to connect automatically.
600
601 @param ssid SSID of the network to connect to
602 @type str
603 @param password password needed to authenticate
604 @type str
605 @return tuple containing a flag indicating success and an error message
606 @rtype tuple of (bool, str)
607 """
608 command = """
609 def modify_boot():
610 add = True
611 try:
612 with open('/boot.py', 'r') as f:
613 for ln in f.readlines():
614 if 'wifi_connect' in ln:
615 add = False
616 break
617 except:
618 pass
619 if add:
620 with open('/boot.py', 'a') as f:
621 f.write('\\nimport wifi_connect\\n')
622 print(True)
623
624 modify_boot()
625 del modify_boot
626 """
627
628 if self._deviceData["wifi_type"] == "picow":
629 country = Preferences.getMicroPython("WifiCountry").upper()
630 secrets = "WIFI_SSID = {0}\nWIFI_KEY = {1}\nWIFI_COUNTRY={2}".format(
631 repr(ssid),
632 repr(password) if password else '""',
633 repr(country) if country else '""'
634 )
635 wifiConnectFile = "picowWiFiConnect.py"
636 else:
637 secrets = "WIFI_SSID = {0}\nWIFI_KEY = {1}\n".format(
638 repr(ssid),
639 repr(password) if password else '""',
640 )
641 wifiConnectFile = "mpyWiFiConnect.py"
642 try:
643 # write secrets file
644 self.putData("/secrets.py", secrets.encode("utf-8"))
645 # copy auto-connect file
646 self.put(
647 os.path.join(
648 os.path.dirname(__file__), "MCUScripts", wifiConnectFile
649 ),
650 "/wifi_connect.py",
651 )
652 except OSError as err:
653 return False, str(err)
654
655 # modify boot.py
656 out, err = self._interface.execute(command)
657 if err:
658 return False, err
659
660 return out.decode("utf-8").strip() == "True", ""
661
662 def removeCredentials(self):
663 """
664 Public method to remove the saved credentials from the connected device.
665
666 @return tuple containing a flag indicating success and an error message
667 @rtype tuple of (bool, str)
668 """
669 try:
670 self.rm("/secrets.py")
671 except OSError as err:
672 return False, str(err)
673
674 return True, ""
594 675
595 def checkInternet(self): 676 def checkInternet(self):
596 """ 677 """
597 Public method to check, if the internet can be reached. 678 Public method to check, if the internet can be reached.
598 679
639 @return tuple containing the list of available networks as a tuple of 'Name', 720 @return tuple containing the list of available networks as a tuple of 'Name',
640 'MAC-Address', 'channel', 'RSSI' and 'security' and an error string 721 'MAC-Address', 'channel', 'RSSI' and 'security' and an error string
641 @rtype tuple of (list of tuple of (str, str, int, int, str), str) 722 @rtype tuple of (list of tuple of (str, str, int, int, str), str)
642 """ 723 """
643 if self._deviceData["wifi_type"] == "picow": 724 if self._deviceData["wifi_type"] == "picow":
725 country = Preferences.getMicroPython("WifiCountry").upper()
644 command = """ 726 command = """
645 def scan_networks(): 727 def scan_networks():
646 import network 728 import network
729 import rp2
730
731 rp2.country({0})
647 732
648 wifi = network.WLAN(network.STA_IF) 733 wifi = network.WLAN(network.STA_IF)
649 active = wifi.active() 734 active = wifi.active()
650 if not active: 735 if not active:
651 wifi.active(True) 736 wifi.active(True)
654 wifi.active(False) 739 wifi.active(False)
655 print(network_list) 740 print(network_list)
656 741
657 scan_networks() 742 scan_networks()
658 del scan_networks 743 del scan_networks
659 """ 744 """.format(repr(country if country else "XX"))
745
660 elif self._deviceData["wifi_type"] == "pimoroni": 746 elif self._deviceData["wifi_type"] == "pimoroni":
661 # TODO: not yet implemented 747 # TODO: not yet implemented
662 pass 748 pass
663 else: 749 else:
664 return super().scanNetworks() 750 return super().scanNetworks()
723 if err: 809 if err:
724 return False, err 810 return False, err
725 else: 811 else:
726 return out.decode("utf-8").strip() == "True", "" 812 return out.decode("utf-8").strip() == "True", ""
727 813
728 def startAccessPoint(self): 814 def startAccessPoint(self, ssid, security=None, password=None):
729 """ 815 """
730 Public method to start the access point interface. 816 Public method to start the access point interface.
731 817
818 @param ssid SSID of the access point
819 @type str
820 @param security security method (defaults to None)
821 @type int (optional)
822 @param password password (defaults to None)
823 @type str (optional)
732 @return tuple containing a flag indicating success and an error message 824 @return tuple containing a flag indicating success and an error message
733 @rtype tuple of (bool, str) 825 @rtype tuple of (bool, str)
734 """ 826 """
827 if security is None or password is None:
828 security = 0
829 password = ""
830
831 if self._deviceData["wifi_type"] == "picow":
832 country = Preferences.getMicroPython("WifiCountry").upper()
833 if security:
834 security = 4 # Pico W supports just WPA/WPA2
835 command = """
836 def start_ap():
837 import network
838 import rp2
839 from time import sleep
840
841 rp2.country({3})
842
843 ap = network.WLAN(network.AP_IF)
844 ap.config(ssid={0}, security={1}, password={2})
845 ap.active(True)
846 sleep(0.1)
847 print(ap.isconnected())
848
849 start_ap()
850 del start_ap
851 """.format(repr(ssid), security, repr(password), repr(country if country else "XX"))
852 elif self._deviceData["wifi_type"] == "pimoroni":
853 # TODO: not yet implemented
854 pass
855 else:
856 return super().startAccessPoint(ssid, security=security, password=password)
857
858 out, err = self._interface.execute(command, timeout=15000)
859 if err:
860 return False, err
861 else:
862 return out.decode("utf-8").strip() == "True", ""
735 863
736 def stopAccessPoint(self): 864 def stopAccessPoint(self):
737 """ 865 """
738 Public method to stop the access point interface. 866 Public method to stop the access point interface.
739 867
746 # TODO: not yet implemented 874 # TODO: not yet implemented
747 pass 875 pass
748 else: 876 else:
749 return super().stopAccessPoint() 877 return super().stopAccessPoint()
750 878
879 def getConnectedClients(self):
880 """
881 Public method to get a list of connected clients.
882
883 @return a tuple containing a list of tuples containing the client MAC-Address
884 and the RSSI (if supported and available) and an error message
885 @rtype tuple of ([(bytes, int)], str)
886 """
887 if self._deviceData["wifi_type"] == "picow":
888 command = """
889 def get_stations():
890 import network
891
892 ap = network.WLAN(network.AP_IF)
893 stations = ap.status('stations')
894 print(stations)
895
896 get_stations()
897 del get_stations
898 """
899 elif self._deviceData["wifi_type"] == "pimoroni":
900 # TODO: not yet implemented
901 pass
902 else:
903 return super().checkInternet()
904
905 out, err = self._interface.execute(command, timeout=10000)
906 if err:
907 return [], err
908
909 clientsList = ast.literal_eval(out.decode("utf-8"))
910 return clientsList, ""
911
751 ############################################################################ 912 ############################################################################
752 ## RP2 only methods below 913 ## RP2 only methods below
753 ############################################################################ 914 ############################################################################
754 915
755 @pyqtSlot() 916 @pyqtSlot()
772 rp2.country({0}) 933 rp2.country({0})
773 """.format(repr(country)) 934 """.format(repr(country))
774 935
775 out, err = self._interface.execute(command) 936 out, err = self._interface.execute(command)
776 if err: 937 if err:
777 self._showError("rp2.country()", err) 938 self.microPython.showError("rp2.country()", err)
778 939
779 940
780 def createDevice(microPythonWidget, deviceType, vid, pid, boardName, serialNumber): 941 def createDevice(microPythonWidget, deviceType, vid, pid, boardName, serialNumber):
781 """ 942 """
782 Function to instantiate a MicroPython device object. 943 Function to instantiate a MicroPython device object.

eric ide

mercurial