src/eric7/MicroPython/Devices/CircuitPythonDevices.py

branch
eric7
changeset 10153
ffe7432f716b
parent 10144
45a9177c8e77
child 10170
6cf1ee737d8f
equal deleted inserted replaced
10152:33e7b9d3f91c 10153:ffe7432f716b
794 str(r.ipv4_subnet) if r.ipv4_subnet else'0.0.0.0', 794 str(r.ipv4_subnet) if r.ipv4_subnet else'0.0.0.0',
795 str(r.ipv4_gateway) if r.ipv4_gateway else'0.0.0.0', 795 str(r.ipv4_gateway) if r.ipv4_gateway else'0.0.0.0',
796 str(r.ipv4_dns) if r.ipv4_dns else'0.0.0.0', 796 str(r.ipv4_dns) if r.ipv4_dns else'0.0.0.0',
797 ), 797 ),
798 'mac': binascii.hexlify(r.mac_address, ':').decode(), 798 'mac': binascii.hexlify(r.mac_address, ':').decode(),
799 'hostname': r.hostname,
800 } 799 }
801 try: 800 try:
802 station['txpower'] = r.tx_power 801 station['txpower'] = r.tx_power
803 except AttributeError: 802 except AttributeError:
804 pass 803 pass
829 str(r.ipv4_subnet_ap) if r.ipv4_subnet_ap else'0.0.0.0', 828 str(r.ipv4_subnet_ap) if r.ipv4_subnet_ap else'0.0.0.0',
830 str(r.ipv4_gateway_ap) if r.ipv4_gateway_ap else'0.0.0.0', 829 str(r.ipv4_gateway_ap) if r.ipv4_gateway_ap else'0.0.0.0',
831 str(r.ipv4_dns) if r.ipv4_dns else'0.0.0.0', 830 str(r.ipv4_dns) if r.ipv4_dns else'0.0.0.0',
832 ), 831 ),
833 'mac': binascii.hexlify(r.mac_address_ap, ':').decode(), 832 'mac': binascii.hexlify(r.mac_address_ap, ':').decode(),
834 'hostname': r.hostname,
835 } 833 }
836 try: 834 try:
837 ap['txpower'] = r.tx_power 835 ap['txpower'] = r.tx_power
838 except AttributeError: 836 except AttributeError:
839 pass 837 pass
840 print(json.dumps(ap)) 838 print(json.dumps(ap))
841 839
842 overall = { 840 overall = {
843 'active': r.enabled 841 'active': r.enabled,
842 'hostname': r.hostname,
844 } 843 }
845 print(json.dumps(overall)) 844 print(json.dumps(overall))
846 845
847 wifi_status() 846 wifi_status()
848 del wifi_status 847 del wifi_status
866 station["ap_security"] 865 station["ap_security"]
867 ) 866 )
868 867
869 return station, ap, overall 868 return station, ap, overall
870 869
871 def connectWifi(self, ssid, password): 870 def connectWifi(self, ssid, password, hostname):
872 """ 871 """
873 Public method to connect a device to a WiFi network. 872 Public method to connect a device to a WiFi network.
874 873
875 @param ssid name (SSID) of the WiFi network 874 @param ssid name (SSID) of the WiFi network
876 @type str 875 @type str
877 @param password password needed to connect 876 @param password password needed to connect
878 @type str 877 @type str
878 @param hostname host name of the device
879 @type str
879 @return tuple containing the connection status and an error string 880 @return tuple containing the connection status and an error string
880 @rtype tuple of (bool, str) 881 @rtype tuple of (bool, str)
881 """ 882 """
882 command = """ 883 command = """
883 def connect_wifi(ssid, password): 884 def connect_wifi(ssid, password, hostname):
884 import json 885 import json
885 import wifi 886 import wifi
886 887
887 r = wifi.radio 888 r = wifi.radio
888 try: 889 try:
890 if hostname:
891 r.hostname = hostname
889 r.start_station() 892 r.start_station()
890 r.connect(ssid, password) 893 r.connect(ssid, password)
891 status = 'connected' 894 status = 'connected'
892 except Exception as exc: 895 except Exception as exc:
893 status = str(exc) 896 status = str(exc)
894 897
895 print(json.dumps({{'connected': r.ipv4_address is not None, 'status': status}})) 898 print(json.dumps({{'connected': r.ipv4_address is not None, 'status': status}}))
896 899
897 connect_wifi({0}, {1}) 900 connect_wifi({0}, {1}, {2})
898 del connect_wifi 901 del connect_wifi
899 """.format( 902 """.format(
900 repr(ssid), 903 repr(ssid),
901 repr(password if password else ""), 904 repr(password if password else ""),
905 repr(hostname),
902 ) 906 )
903 907
904 with EricOverrideCursor(): 908 with EricOverrideCursor():
905 out, err = self.executeCommands( 909 out, err = self.executeCommands(
906 command, mode=self._submitMode, timeout=15000 910 command, mode=self._submitMode, timeout=15000
988 if err: 992 if err:
989 return False 993 return False
990 994
991 return out.strip() == b"True" 995 return out.strip() == b"True"
992 996
993 def writeCredentials(self, ssid, password): 997 def writeCredentials(self, ssid, password, hostname, country): # noqa: U100
994 """ 998 """
995 Public method to write the given credentials to the connected device and modify 999 Public method to write the given credentials to the connected device and modify
996 the start script to connect automatically. 1000 the start script to connect automatically.
997 1001
998 @param ssid SSID of the network to connect to 1002 @param ssid SSID of the network to connect to
999 @type str 1003 @type str
1000 @param password password needed to authenticate 1004 @param password password needed to authenticate
1001 @type str 1005 @type str
1006 @param hostname host name of the device
1007 @type str
1008 @param country WiFi country code (unused)
1009 @type str
1002 @return tuple containing a flag indicating success and an error message 1010 @return tuple containing a flag indicating success and an error message
1003 @rtype tuple of (bool, str) 1011 @rtype tuple of (bool, str)
1004 """ 1012 """
1005 if not self.__deviceVolumeMounted(): 1013 if not self.__deviceVolumeMounted():
1006 return False, self.tr("The device volume is not available.") 1014 return False, self.tr("The device volume is not available.")
1008 workspace = self.getWorkspace() 1016 workspace = self.getWorkspace()
1009 1017
1010 if Globals.versionToTuple(self._deviceData["release"]) >= (8, 0, 0): 1018 if Globals.versionToTuple(self._deviceData["release"]) >= (8, 0, 0):
1011 # CircuitPython >= 8.0.0: generate 'settings.toml' file 1019 # CircuitPython >= 8.0.0: generate 'settings.toml' file
1012 contents = ( 1020 contents = (
1013 'CIRCUITPY_WIFI_SSID = "{0}"\nCIRCUITPY_WIFI_PASSWORD = "{1}"\n'.format( 1021 'CIRCUITPY_WIFI_SSID = "{0}"\nCIRCUITPY_WIFI_PASSWORD = "{1}"\n'
1014 ssid, password 1022 'CIRCUITPY_WIFI_HOSTNAME = "{2}"\n'.format(ssid, password, hostname)
1015 )
1016 ) 1023 )
1017 filename = os.path.join(workspace, "settings.toml") 1024 filename = os.path.join(workspace, "settings.toml")
1018 if os.path.exists(filename): 1025 if os.path.exists(filename):
1019 ok = EricMessageBox.yesNo( 1026 ok = EricMessageBox.yesNo(
1020 None, 1027 None,
1036 1043
1037 else: 1044 else:
1038 # CircuitPython < 8.0.0: generate a secrets.py script 1045 # CircuitPython < 8.0.0: generate a secrets.py script
1039 # step 1: generate the secrets.py file 1046 # step 1: generate the secrets.py file
1040 contents = ( 1047 contents = (
1041 'secrets = {{\n "ssid": "{0}",\n "password": "{1}",\n}}\n'.format( 1048 'secrets = {{\n "ssid": "{0}",\n "password": "{1}",\n'
1042 ssid, password 1049 ' "hostname": "{2}",\n}}\n'.format(ssid, password, hostname)
1043 )
1044 ) 1050 )
1045 filename = os.path.join(workspace, "secrets.py") 1051 filename = os.path.join(workspace, "secrets.py")
1046 if os.path.exists(filename): 1052 if os.path.exists(filename):
1047 ok = EricMessageBox.yesNo( 1053 ok = EricMessageBox.yesNo(
1048 None, 1054 None,
1209 if err: 1215 if err:
1210 return False, err 1216 return False, err
1211 else: 1217 else:
1212 return out.decode("utf-8").strip() == "True", "" 1218 return out.decode("utf-8").strip() == "True", ""
1213 1219
1214 def startAccessPoint(self, ssid, security=None, password=None, ifconfig=None): 1220 def startAccessPoint(
1221 self,
1222 ssid,
1223 security=None,
1224 password=None,
1225 hostname=None,
1226 ifconfig=None,
1227 ):
1215 """ 1228 """
1216 Public method to start the access point interface. 1229 Public method to start the access point interface.
1217 1230
1218 @param ssid SSID of the access point 1231 @param ssid SSID of the access point
1219 @type str 1232 @type str
1220 @param security security method (defaults to None) 1233 @param security security method (defaults to None)
1221 @type int (optional) 1234 @type int (optional)
1222 @param password password (defaults to None) 1235 @param password password (defaults to None)
1236 @type str (optional)
1237 @param hostname host name of the device (defaults to None)
1223 @type str (optional) 1238 @type str (optional)
1224 @param ifconfig IPv4 configuration for the access point if not default 1239 @param ifconfig IPv4 configuration for the access point if not default
1225 (IPv4 address, netmask, gateway address, DNS server address) 1240 (IPv4 address, netmask, gateway address, DNS server address)
1226 @type tuple of (str, str, str, str) 1241 @type tuple of (str, str, str, str)
1227 @return tuple containing a flag indicating success and an error message 1242 @return tuple containing a flag indicating success and an error message
1240 " WiFi access point." 1255 " WiFi access point."
1241 ), 1256 ),
1242 ) 1257 )
1243 1258
1244 command = """ 1259 command = """
1245 def start_ap(ssid, password): 1260 def start_ap(ssid, password, hostname):
1246 import wifi 1261 import wifi
1247 1262
1248 r = wifi.radio 1263 r = wifi.radio
1264 r.enabled = True
1265 if hostname:
1266 r.hostname = hostname
1249 try: 1267 try:
1250 r.start_ap(ssid, password, authmode={2}) 1268 r.start_ap(ssid, password, authmode={3})
1251 except ValueError as exc: 1269 except (NotImplementedError, ValueError) as exc:
1252 print('Error:', str(exc)) 1270 print('Error:', str(exc))
1253 1271
1254 start_ap({0}, {1}) 1272 start_ap({0}, {1}, {2})
1255 del start_ap 1273 del start_ap
1256 """.format( 1274 """.format(
1257 repr(ssid), repr(password), authmode 1275 repr(ssid), repr(password), repr(hostname), authmode
1258 ) 1276 )
1259 1277
1260 out, err = self.executeCommands(command, mode=self._submitMode, timeout=15000) 1278 out, err = self.executeCommands(command, mode=self._submitMode, timeout=15000)
1261 if err: 1279 if err:
1262 return False, err 1280 return False, err
1394 status.append((self.tr("Chip Type"), ethStatus["chip"])) 1412 status.append((self.tr("Chip Type"), ethStatus["chip"]))
1395 status.append((self.tr("max. Sockets"), ethStatus["max_sockets"])) 1413 status.append((self.tr("max. Sockets"), ethStatus["max_sockets"]))
1396 1414
1397 return status 1415 return status
1398 1416
1399 def connectToLan(self, config): 1417 def connectToLan(self, config, hostname):
1400 """ 1418 """
1401 Public method to connect the connected device to the LAN. 1419 Public method to connect the connected device to the LAN.
1402 1420
1403 Note: The MAC address of the interface is configured with the WIZ 1421 Note: The MAC address of the interface is configured with the WIZ
1404 1422
1405 @param config configuration for the connection (either the string 'dhcp' 1423 @param config configuration for the connection (either the string 'dhcp'
1406 for a dynamic address or a tuple of four strings with the IPv4 parameters. 1424 for a dynamic address or a tuple of four strings with the IPv4 parameters.
1407 @type str or tuple of (str, str, str, str) 1425 @type str or tuple of (str, str, str, str)
1426 @param hostname host name of the device
1427 @type str
1408 @return tuple containing a flag indicating success and an error message 1428 @return tuple containing a flag indicating success and an error message
1409 @rtype tuple of (bool, str) 1429 @rtype tuple of (bool, str)
1410 """ 1430 """
1411 command = """{0} 1431 command = """{0}
1412 def connect_lan(config): 1432 def connect_lan(config, hostname):
1413 from adafruit_wiznet5k import adafruit_wiznet5k 1433 from adafruit_wiznet5k import adafruit_wiznet5k
1414 1434
1415 w5x00_init() 1435 w5x00_init()
1416 1436
1417 nic.mac_address = adafruit_wiznet5k._DEFAULT_MAC 1437 nic.mac_address = adafruit_wiznet5k._DEFAULT_MAC
1418 if config == 'dhcp': 1438 if config == 'dhcp':
1419 nic.set_dhcp(response_timeout=14) 1439 nic.set_dhcp(hostname=hostname)
1420 else: 1440 else:
1421 nic.ifconfig = ( 1441 nic.ifconfig = (
1422 nic.unpretty_ip(config[0]), 1442 nic.unpretty_ip(config[0]),
1423 nic.unpretty_ip(config[1]), 1443 nic.unpretty_ip(config[1]),
1424 nic.unpretty_ip(config[2]), 1444 nic.unpretty_ip(config[2]),
1425 tuple(int(a) for a in config[3].split('.')), 1445 tuple(int(a) for a in config[3].split('.')),
1426 ) 1446 )
1427 print(nic.ifconfig[0] != b'\x00\x00\x00\x00') 1447 print(nic.ifconfig[0] != b'\x00\x00\x00\x00')
1428 1448
1429 connect_lan({1}) 1449 connect_lan({1}, {2})
1430 del connect_lan, w5x00_init 1450 del connect_lan, w5x00_init
1431 """.format( 1451 """.format(
1432 WiznetUtilities.cpyWiznetInit(), "'dhcp'" if config == "dhcp" else config 1452 WiznetUtilities.cpyWiznetInit(),
1453 "'dhcp'" if config == "dhcp" else config,
1454 repr(hostname) if hostname else "''",
1433 ) 1455 )
1434 1456
1435 with EricOverrideCursor(): 1457 with EricOverrideCursor():
1436 out, err = self.executeCommands( 1458 out, err = self.executeCommands(
1437 command, mode=self._submitMode, timeout=15000 1459 command, mode=self._submitMode, timeout=15000
1543 # The WIZnet 5x00 interface cannot be switched off explicitly. That means, 1565 # The WIZnet 5x00 interface cannot be switched off explicitly. That means,
1544 # disconnect from the LAN is all we can do. 1566 # disconnect from the LAN is all we can do.
1545 1567
1546 return self.disconnectFromLan() 1568 return self.disconnectFromLan()
1547 1569
1548 def writeLanAutoConnect(self, config): 1570 def writeLanAutoConnect(self, config, hostname):
1549 """ 1571 """
1550 Public method to generate a script and associated configuration to connect the 1572 Public method to generate a script and associated configuration to connect the
1551 device to the LAN during boot time. 1573 device to the LAN during boot time.
1552 1574
1553 @param config configuration for the connection (either the string 'dhcp' 1575 @param config configuration for the connection (either the string 'dhcp'
1554 for a dynamic address or a tuple of four strings with the IPv4 parameters. 1576 for a dynamic address or a tuple of four strings with the IPv4 parameters.
1555 @type str or tuple of (str, str, str, str) 1577 @type str or tuple of (str, str, str, str)
1578 @param hostname host name of the device
1579 @type str
1556 @return tuple containing a flag indicating success and an error message 1580 @return tuple containing a flag indicating success and an error message
1557 @rtype tuple of (bool, str) 1581 @rtype tuple of (bool, str)
1558 """ 1582 """
1559 if not self.__deviceVolumeMounted(): 1583 if not self.__deviceVolumeMounted():
1560 return False, self.tr("The device volume is not available.") 1584 return False, self.tr("The device volume is not available.")
1567 { 1591 {
1568 "WIZNET_IFCONFIG_0": '"dhcp"', 1592 "WIZNET_IFCONFIG_0": '"dhcp"',
1569 "WIZNET_IFCONFIG_1": "", 1593 "WIZNET_IFCONFIG_1": "",
1570 "WIZNET_IFCONFIG_2": "", 1594 "WIZNET_IFCONFIG_2": "",
1571 "WIZNET_IFCONFIG_3": "", 1595 "WIZNET_IFCONFIG_3": "",
1596 "WIZNET_HOSTNAME": '"{0}"'.format(hostname) if hostname else '""',
1572 } 1597 }
1573 if config == "dhcp" 1598 if config == "dhcp"
1574 else { 1599 else {
1575 "WIZNET_IFCONFIG_0": '"{0}"'.format(config[0]), 1600 "WIZNET_IFCONFIG_0": '"{0}"'.format(config[0]),
1576 "WIZNET_IFCONFIG_1": '"{0}"'.format(config[1]), 1601 "WIZNET_IFCONFIG_1": '"{0}"'.format(config[1]),
1586 os.path.dirname(__file__), "MCUScripts", "picoWiznetConnectCpy8.py" 1611 os.path.dirname(__file__), "MCUScripts", "picoWiznetConnectCpy8.py"
1587 ) 1612 )
1588 1613
1589 else: 1614 else:
1590 # step 1: generate the wiznet_config.py file 1615 # step 1: generate the wiznet_config.py file
1591 ifconfig = "ifconfig = {0}\n".format( 1616 ifconfig = "ifconfig = {0}\nhostname={1}\n".format(
1592 "'dhcp'" if config == "dhcp" else config 1617 "'dhcp'" if config == "dhcp" else config,
1618 repr(hostname) if hostname else "''",
1593 ) 1619 )
1594 filename = os.path.join(workspace, "wiznet_config.py") 1620 filename = os.path.join(workspace, "wiznet_config.py")
1595 if os.path.exists(filename): 1621 if os.path.exists(filename):
1596 ok = EricMessageBox.yesNo( 1622 ok = EricMessageBox.yesNo(
1597 None, 1623 None,

eric ide

mercurial