src/eric7/MicroPython/Devices/EspDevices.py

branch
eric7
changeset 10153
ffe7432f716b
parent 10144
45a9177c8e77
child 10170
6cf1ee737d8f
equal deleted inserted replaced
10152:33e7b9d3f91c 10153:ffe7432f716b
613 613
614 ################################################################## 614 ##################################################################
615 ## Methods below implement WiFi related methods 615 ## Methods below implement WiFi related methods
616 ################################################################## 616 ##################################################################
617 617
618 def addDeviceWifiEntries(self, menu):
619 """
620 Public method to add device specific entries to the given menu.
621
622 @param menu reference to the context menu
623 @type QMenu
624 """
625 if not self.hasCircuitPython():
626 menu.addSeparator()
627 menu.addAction(self.tr("Set Country"), self.__setCountry)
628 menu.addAction(self.tr("Reset Country"), self.__resetCountry)
629
618 def hasWifi(self): 630 def hasWifi(self):
619 """ 631 """
620 Public method to check the availability of WiFi. 632 Public method to check the availability of WiFi.
621 633
622 @return tuple containing a flag indicating the availability of WiFi 634 @return tuple containing a flag indicating the availability of WiFi
626 if self.hasCircuitPython(): 638 if self.hasCircuitPython():
627 self.__createCpyDevice() 639 self.__createCpyDevice()
628 return self.__cpyDevice.hasWifi() 640 return self.__cpyDevice.hasWifi()
629 641
630 return True, "esp32" 642 return True, "esp32"
643
644 def hasWifiCountry(self):
645 """
646 Public method to check, if the device has support to set the WiFi country.
647
648 @return flag indicating the support of WiFi country
649 @rtype bool
650 """
651 return True
631 652
632 def getWifiData(self): 653 def getWifiData(self):
633 """ 654 """
634 Public method to get data related to the current WiFi status. 655 Public method to get data related to the current WiFi status.
635 656
680 print(ujson.dumps(ap)) 701 print(ujson.dumps(ap))
681 702
682 overall = { 703 overall = {
683 'active': station['active'] or ap['active'] 704 'active': station['active'] or ap['active']
684 } 705 }
706 try:
707 overall['hostname'] = network.hostname()
708 except AttributeError:
709 pass
710 try:
711 overall['country'] = network.country()
712 except AttributeError:
713 pass
685 print(ujson.dumps(overall)) 714 print(ujson.dumps(overall))
686 715
687 wifi_status() 716 wifi_status()
688 del wifi_status 717 del wifi_status
689 """ 718 """
704 ap["status"] = self.__statusTranslations[ap["status"]] 733 ap["status"] = self.__statusTranslations[ap["status"]]
705 except KeyError: 734 except KeyError:
706 ap["status"] = str(ap["status"]) 735 ap["status"] = str(ap["status"])
707 return station, ap, overall 736 return station, ap, overall
708 737
709 def connectWifi(self, ssid, password): 738 def connectWifi(self, ssid, password, hostname):
710 """ 739 """
711 Public method to connect a device to a WiFi network. 740 Public method to connect a device to a WiFi network.
712 741
713 @param ssid name (SSID) of the WiFi network 742 @param ssid name (SSID) of the WiFi network
714 @type str 743 @type str
715 @param password password needed to connect 744 @param password password needed to connect
716 @type str 745 @type str
746 @param hostname host name of the device
747 @type str
717 @return tuple containing the connection status and an error string 748 @return tuple containing the connection status and an error string
718 @rtype tuple of (bool, str) 749 @rtype tuple of (bool, str)
719 """ 750 """
720 if self.hasCircuitPython(): 751 if self.hasCircuitPython():
721 return self.__cpyDevice.connectWifi(ssid, password) 752 return self.__cpyDevice.connectWifi(ssid, password, hostname)
722 753
723 command = """ 754 command = """
724 def connect_wifi(ssid, password): 755 def connect_wifi(ssid, password, hostname):
725 import network 756 import network
726 import ujson 757 import ujson
727 from time import sleep 758 from time import sleep
759
760 if hostname:
761 try:
762 network.hostname(hostname)
763 except AttributeError:
764 pass
728 765
729 wifi = network.WLAN(network.STA_IF) 766 wifi = network.WLAN(network.STA_IF)
730 wifi.active(False) 767 wifi.active(False)
731 wifi.active(True) 768 wifi.active(True)
732 wifi.connect(ssid, password) 769 wifi.connect(ssid, password)
735 max_wait -= 1 772 max_wait -= 1
736 sleep(0.1) 773 sleep(0.1)
737 status = wifi.status() 774 status = wifi.status()
738 print(ujson.dumps({{'connected': wifi.isconnected(), 'status': status}})) 775 print(ujson.dumps({{'connected': wifi.isconnected(), 'status': status}}))
739 776
740 connect_wifi({0}, {1}) 777 connect_wifi({0}, {1}, {2})
741 del connect_wifi 778 del connect_wifi
742 """.format( 779 """.format(
743 repr(ssid), 780 repr(ssid),
744 repr(password if password else ""), 781 repr(password if password else ""),
782 repr(hostname),
745 ) 783 )
746 784
747 with EricOverrideCursor(): 785 with EricOverrideCursor():
748 out, err = self.executeCommands( 786 out, err = self.executeCommands(
749 command, mode=self._submitMode, timeout=15000 787 command, mode=self._submitMode, timeout=15000
845 if err: 883 if err:
846 return False 884 return False
847 885
848 return out.strip() == b"True" 886 return out.strip() == b"True"
849 887
850 def writeCredentials(self, ssid, password): 888 def writeCredentials(self, ssid, password, hostname, country):
851 """ 889 """
852 Public method to write the given credentials to the connected device and modify 890 Public method to write the given credentials to the connected device and modify
853 the start script to connect automatically. 891 the start script to connect automatically.
854 892
855 @param ssid SSID of the network to connect to 893 @param ssid SSID of the network to connect to
856 @type str 894 @type str
857 @param password password needed to authenticate 895 @param password password needed to authenticate
858 @type str 896 @type str
897 @param hostname host name of the device
898 @type str
899 @param country WiFi country code
900 @type str
859 @return tuple containing a flag indicating success and an error message 901 @return tuple containing a flag indicating success and an error message
860 @rtype tuple of (bool, str) 902 @rtype tuple of (bool, str)
861 """ 903 """
862 if self.hasCircuitPython(): 904 if self.hasCircuitPython():
863 return self.__cpyDevice.writeCredentials(ssid, password) 905 return self.__cpyDevice.writeCredentials(ssid, password, hostname)
864 906
865 nvsCommand = """ 907 nvsCommand = """
866 def save_wifi_creds(ssid, password): 908 def save_wifi_creds(ssid, password, hostname, country):
867 import esp32 909 import esp32
868 910
869 nvs = esp32.NVS('wifi_creds') 911 nvs = esp32.NVS('wifi_creds')
870 nvs.set_blob('ssid', ssid) 912 nvs.set_blob('ssid', ssid)
871 nvs.set_blob('password', password) 913 nvs.set_blob('password', password)
914 nvs.set_blob('hostname', hostname)
915 nvs.set_blob('country', country)
872 nvs.commit() 916 nvs.commit()
873 917
874 save_wifi_creds({0}, {1}) 918 save_wifi_creds({0}, {1}, {2}, {3})
875 del save_wifi_creds 919 del save_wifi_creds
876 """.format( 920 """.format(
877 repr(ssid), repr(password) if password else "''" 921 repr(ssid),
922 repr(password) if password else "''",
923 repr(hostname) if hostname else "''",
924 repr(country.upper()) if country else "''",
878 ) 925 )
879 bootCommand = """ 926 bootCommand = """
880 def modify_boot(): 927 def modify_boot():
881 add = True 928 add = True
882 try: 929 try:
1073 if err: 1120 if err:
1074 return False, err 1121 return False, err
1075 else: 1122 else:
1076 return out.decode("utf-8").strip() == "True", "" 1123 return out.decode("utf-8").strip() == "True", ""
1077 1124
1078 def startAccessPoint(self, ssid, security=None, password=None, ifconfig=None): 1125 def startAccessPoint(
1126 self,
1127 ssid,
1128 security=None,
1129 password=None,
1130 hostname=None,
1131 ifconfig=None,
1132 ):
1079 """ 1133 """
1080 Public method to start the access point interface. 1134 Public method to start the access point interface.
1081 1135
1082 @param ssid SSID of the access point 1136 @param ssid SSID of the access point
1083 @type str 1137 @type str
1084 @param security security method (defaults to None) 1138 @param security security method (defaults to None)
1085 @type int (optional) 1139 @type int (optional)
1086 @param password password (defaults to None) 1140 @param password password (defaults to None)
1087 @type str (optional) 1141 @type str (optional)
1142 @param hostname host name of the device (defaults to None)
1143 @type str (optional)
1088 @param ifconfig IPv4 configuration for the access point if not default 1144 @param ifconfig IPv4 configuration for the access point if not default
1089 (IPv4 address, netmask, gateway address, DNS server address) 1145 (IPv4 address, netmask, gateway address, DNS server address)
1090 @type tuple of (str, str, str, str) 1146 @type tuple of (str, str, str, str)
1091 @return tuple containing a flag indicating success and an error message 1147 @return tuple containing a flag indicating success and an error message
1092 @rtype tuple of (bool, str) 1148 @rtype tuple of (bool, str)
1093 """ 1149 """
1094 if self.hasCircuitPython(): 1150 if self.hasCircuitPython():
1095 return self.__cpyDevice.startAccessPoint( 1151 return self.__cpyDevice.startAccessPoint(
1096 ssid, security=security, password=password, ifconfig=ifconfig 1152 ssid,
1153 security=security,
1154 password=password,
1155 hostname=hostname,
1156 ifconfig=ifconfig,
1097 ) 1157 )
1098 1158
1099 if security is None or password is None: 1159 if security is None or password is None:
1100 security = 0 1160 security = 0
1101 password = "" 1161 password = ""
1102 if security > 4: 1162 if security > 4:
1103 security = 4 # security >4 cause an error thrown by the ESP32 1163 security = 4 # security >4 cause an error thrown by the ESP32
1104 1164
1105 command = """ 1165 command = """
1106 def start_ap(ssid, authmode, password, ifconfig): 1166 def start_ap(ssid, authmode, password, hostname, ifconfig):
1107 import network 1167 import network
1168
1169 if hostname:
1170 try:
1171 network.hostname(hostname)
1172 except AttributeError:
1173 pass
1108 1174
1109 ap = network.WLAN(network.AP_IF) 1175 ap = network.WLAN(network.AP_IF)
1110 ap.active(False) 1176 ap.active(False)
1111 if ifconfig: 1177 if ifconfig:
1112 ap.ifconfig(ifconfig) 1178 ap.ifconfig(ifconfig)
1114 try: 1180 try:
1115 ap.config(ssid=ssid, authmode=authmode, password=password) 1181 ap.config(ssid=ssid, authmode=authmode, password=password)
1116 except: 1182 except:
1117 ap.config(essid=ssid, authmode=authmode, password=password) 1183 ap.config(essid=ssid, authmode=authmode, password=password)
1118 1184
1119 start_ap({0}, {1}, {2}, {3}) 1185 start_ap({0}, {1}, {2}, {3}, {4})
1120 del start_ap 1186 del start_ap
1121 """.format( 1187 """.format(
1122 repr(ssid), security, repr(password), ifconfig 1188 repr(ssid), security, repr(password), repr(hostname), ifconfig
1123 ) 1189 )
1124 1190
1125 out, err = self.executeCommands(command, mode=self._submitMode, timeout=15000) 1191 out, err = self.executeCommands(command, mode=self._submitMode, timeout=15000)
1126 if err: 1192 if err:
1127 return False, err 1193 return False, err
1256 out, err = self.executeCommands(command, mode=self._submitMode) 1322 out, err = self.executeCommands(command, mode=self._submitMode)
1257 if err: 1323 if err:
1258 return False, err 1324 return False, err
1259 1325
1260 return out.decode("utf-8").strip() == "True", "" 1326 return out.decode("utf-8").strip() == "True", ""
1327
1328 @pyqtSlot()
1329 def __setCountry(self):
1330 """
1331 Private slot to configure the country of the connected ESP32 device.
1332
1333 The country is the two-letter ISO 3166-1 Alpha-2 country code.
1334 """
1335 from ..WifiDialogs.WifiCountryDialog import WifiCountryDialog
1336
1337 dlg = WifiCountryDialog()
1338 if dlg.exec() == QDialog.DialogCode.Accepted:
1339 country, remember = dlg.getCountry()
1340 if remember:
1341 Preferences.setMicroPython("WifiCountry", country)
1342
1343 command = """
1344 try:
1345 import network
1346 network.country({0})
1347 except AttributeError:
1348 pass
1349 """.format(
1350 repr(country)
1351 )
1352
1353 out, err = self.executeCommands(command, mode=self._submitMode)
1354 if err:
1355 self.microPython.showError("country()", err)
1356
1357 @pyqtSlot()
1358 def __resetCountry(self):
1359 """
1360 Private slot to reset the country of the connected ESP32 device.
1361
1362 The country is the two-letter ISO 3166-1 Alpha-2 country code. This method
1363 resets it to the default code 'XX' representing the "worldwide" region.
1364 """
1365 command = """
1366 try:
1367 import network
1368 network.country('XX')
1369 except AttributeError:
1370 pass
1371 """
1372
1373 out, err = self.executeCommands(command, mode=self._submitMode)
1374 if err:
1375 self.microPython.showError("country()", err)
1261 1376
1262 ################################################################## 1377 ##################################################################
1263 ## Methods below implement Bluetooth related methods 1378 ## Methods below implement Bluetooth related methods
1264 ################################################################## 1379 ##################################################################
1265 1380

eric ide

mercurial