├── LICENSE
├── README.md
├── boot.py
├── config.txt
├── docs
└── help.txt
├── main.py
├── pico-shell.png
├── telnet
└── utelnetserver.py
└── utils.py
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2025 Patrick
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # PicoShell
2 |
3 | **PicoShell** is a lightweight, real-time command-line interface (CLI) for the Raspberry Pi Pico W 2 (RP2350 dual-core), built entirely in MicroPython. It brings a minimal UNIX-style shell to embedded hardware with support for Wi-Fi networking, filesystem interaction, script execution, telnet access, and more.
4 |
5 | ---
6 | 
7 |
8 |
9 | ## Features
10 |
11 | - Basic shell command interface over USB or Telnet
12 | - Wi-Fi networking with persistent config
13 | - Telnet daemon that autostarts on successful network connection
14 | - Filesystem tools: create, read, delete, navigate
15 | - Script runner and file downloader
16 | - System utilities: memory, clock speed, device info, and overclocking
17 | - Built for expansion and real task threading with RP2350
18 |
19 | ---
20 |
21 | ## Commands
22 |
23 | ### General
24 |
25 | | Command | Description |
26 | |--------------|--------------------------------------|
27 | | `help`, `h` | Show this help message |
28 | | `about` | Show shell version & system info |
29 | | `clear` | Clear the terminal display |
30 | | `exit` | Exits back to MicroPython |
31 |
32 | ### Filesystem
33 |
34 | | Command | Description |
35 | |----------------|--------------------------------------|
36 | | `pwd` | Print current working directory |
37 | | `ls` | List files and directories |
38 | | `cd
` | Change directory |
39 | | `mkdir ` | Create a directory |
40 | | `rmdir ` | Remove a directory |
41 | | `rm ` | Delete a file |
42 | | `read ` | Print contents of a file |
43 |
44 | ### Networking
45 |
46 | | Command | Description |
47 | |----------------------|----------------------------------------|
48 | | `wifi` | Connect to Wi-Fi using config file |
49 | | `ifconfig` | Show IP and network info |
50 | | `ping ` | Ping a host by IP or domain |
51 | | `curl ` | Fetch and display content from URL |
52 | | `clone [name]` | Download file from GitHub/raw URL |
53 | | `scan` | Scan nearby Wi-Fi networks |
54 | | `pmap ` | Nmap-style port scanner |
55 |
56 | ### Telnet
57 |
58 | | Command | Description |
59 | |------------------|----------------------------------------|
60 | | `telnet launch` | Start the telnet server |
61 | | `telnet stop` | Stop the telnet server |
62 |
63 | ### Scripts
64 |
65 | | Command | Description |
66 | |------------------|----------------------------------------|
67 | | `run ` | Execute a Python script from storage |
68 |
69 | ### System
70 |
71 | | Command | Description |
72 | |-------------------|----------------------------------------|
73 | | `setclock ` | Set CPU frequency (40–260 MHz) |
74 | | `clock` | Show current CPU clock speed |
75 | | `dspace` | Show available storage |
76 | | `ram` | Show current RAM usage |
77 | | `sysinfo` | Show detailed system/platform info |
78 |
79 | ---
80 |
81 | ## Project Structure
82 |
83 | ```
84 | boot.py # Wi-Fi and Telnet auto-connect on boot
85 | Main.py # Main CLI loop
86 | utils.py # Core shell commands
87 | utelnetserver.py # Lightweight Telnet server
88 | help.txt # CLI help text
89 | config.txt # Wi-Fi credentials (SSID=..., PASSWORD=...)
90 | ```
91 |
92 | ---
93 |
94 | ## Getting Started
95 |
96 | ### 1. Flash MicroPython to Your Pico W 2
97 |
98 | - Download the latest **MicroPython UF2 firmware** for the **Pico W 2 (RP2350)** from the [official MicroPython downloads page](https://micropython.org/download/rp2-pico-w/).
99 | - Hold the **BOOTSEL** button while plugging in your Pico to your computer. It will appear as a USB drive.
100 | - Drag and drop the downloaded `.uf2` file onto that drive.
101 | - The Pico will reboot into MicroPython mode.
102 |
103 | ### 2. Upload PicoShell Files
104 |
105 | - Upload the following to the root of the Pico filesystem:
106 |
107 | - `boot.py`
108 | - `Main.py`
109 | - `utils.py`
110 | - `telnet`
111 | - `docs`
112 | - `config.txt`
113 |
114 | You can use any of the following tools:
115 |
116 | #### Thonny IDE (GUI)
117 |
118 | - Open [Thonny](https://thonny.org)
119 | - Select "MicroPython (Raspberry Pi Pico)"
120 | - Use the file browser to upload each file listed above
121 |
122 | #### mpremote (CLI)
123 |
124 | ```bash
125 | mpremote connect ttyUSB0 fs cp boot.py :
126 | mpremote connect ttyUSB0 fs cp Main.py :
127 | mpremote connect ttyUSB0 fs cp utils.py :
128 | mpremote connect ttyUSB0 fs cp utelnetserver.py :
129 | mpremote connect ttyUSB0 fs cp help.txt :
130 | mpremote connect ttyUSB0 fs cp config.txt :
131 | ```
132 |
133 | > Replace `ttyUSB0` with your actual serial port (e.g., `COM3` on Windows).
134 |
135 | #### rshell / ampy
136 |
137 | - Use `rshell` or `ampy` to push files to `/` on the board.
138 |
139 | ### 3. Configure Wi-Fi
140 |
141 | Create a file called `config.txt` on the Pico containing:
142 |
143 | ```
144 | SSID=YourNetwork
145 | PASSWORD=YourPassword
146 | ```
147 |
148 | - No spaces around the `=`
149 | - No quotes
150 | - Must be exact format
151 |
152 | ### 4. Run PicoShell
153 |
154 | - Reset or power on the Pico W
155 | - It will:
156 | - Connect to Wi-Fi using `config.txt`
157 | - Auto-start the telnet server
158 | - Drop into CLI via USB serial or Telnet if online
159 |
160 | ---
161 |
162 | ## License
163 |
164 | MIT License — use it, modify it, ship it, just don’t pretend you made it.
165 |
166 | ---
167 |
--------------------------------------------------------------------------------
/boot.py:
--------------------------------------------------------------------------------
1 | import utils
2 | import network
3 | import time
4 | from telnet import utelnetserver
5 |
6 | wlan = network.WLAN(network.STA_IF)
7 | time.sleep(3)
8 | try:
9 | with open('config.txt') as f:
10 | ssid, password = utils.read_wifi_config('config.txt')
11 | utils.auto_connect(ssid, password)
12 | print('Initializing...')
13 |
14 | time.sleep(10)
15 |
16 | if wlan.isconnected():
17 | print("Connected! Starting telnet...")
18 | utelnetserver.start()
19 |
20 | else:
21 | print("Still trying to connect")
22 | except OSError:
23 | print("config.txt not found. Skipping Wi-Fi connection.")
24 |
25 | try:
26 | print("Starting PicoShell...")
27 | time.sleep(2)
28 | import main
29 | except Exception as e:
30 | print("Error:",e)
31 |
--------------------------------------------------------------------------------
/config.txt:
--------------------------------------------------------------------------------
1 | SSID=
2 | PASSWORD=
--------------------------------------------------------------------------------
/docs/help.txt:
--------------------------------------------------------------------------------
1 | Available Commands:
2 |
3 | help, h Show this help message
4 | wifi Manually scan and connect to a Wi-Fi network
5 | ifconfig Show network interface configuration (IP address, etc.)
6 | sysinfo Display system info
7 | dspace Shows the available disk space on the device
8 | ram Shows the current RAM usage
9 |
10 | Filesystem Commands:
11 | pwd Print the current working directory
12 | ls List files and directories
13 | cd Change current directory
14 | mkdir Create a new directory
15 | rmdir Remove a directory
16 | rm Delete a file
17 | read Prints the contents of a file
18 |
19 |
20 | Script & Networking:
21 | run Execute a Python script from storage
22 | clone [name] Download a .py or .txt file from the internet (GitHub raw supported)
23 | curl Fetch and display content from a URL
24 | ping Ping a host by domain or IP
25 | scan Scan for local networks
26 | pmap Nmap-style port scanner that will check for open ports on a designated network
27 |
28 | Telnet:
29 | telnet launch Start a telnet server.
30 | telnet stop Stop the telnet server.
31 | Note: Telnet is started by default if the device is able to successfully connect to Wifi.
32 |
33 | System:
34 | clear Clear the screen
35 | about Show system version and shell info
36 | setclock Set the CPU clock speed (allowed range: 40–260 MHz)
37 | clock Show the current CPU clock speed
38 | temp Returns the CPU temperature
39 | freemem Force Garbage collection to free as much memory as possible.
40 |
41 | Notes:
42 | - Use raw GitHub URLs when cloning (https://raw.githubusercontent.com/...)
43 | - Clone automatically saves using the file's name unless you specify one
44 |
--------------------------------------------------------------------------------
/main.py:
--------------------------------------------------------------------------------
1 | import os
2 | import utils
3 | import network
4 | import platform
5 | import machine
6 | import gc
7 | from machine import Pin
8 | import time
9 | ###
10 | bold = "\033[1m"
11 | green = "\033[32m"
12 | blue = "\033[34m"
13 | reset = "\033[0m"
14 | its = 0
15 | led = Pin("LED", Pin.OUT)
16 | blink = 0
17 | blinked = False
18 | sys_info = os.uname()
19 |
20 | while True:
21 | try:
22 | if not blinked:
23 | while blink < 4:
24 | led.on()
25 | time.sleep(0.2)
26 | led.off()
27 | time.sleep(0.2)
28 | blink += 1
29 | blinked = True
30 | command = input(f"{bold}{green}Pico@{sys_info.sysname}{reset}:{blue}{os.getcwd()}{reset}$ ")
31 |
32 | if command == 'wifi':
33 | utils.getWifi()
34 |
35 | elif command == 'help' or command == 'h':
36 | try:
37 | with open("/docs/help.txt") as f:
38 | print(f.read())
39 | except Exception as e:
40 | print("Help file does not exist.", e)
41 |
42 | elif command == 'ls':
43 | utils.ls()
44 |
45 | elif command == 'exit':
46 | break
47 |
48 | elif command.startswith("run "):
49 | script_name = command[4:].strip()
50 | utils.run(script_name)
51 |
52 | elif command.startswith("cd "):
53 | dir = command[3:].strip()
54 | utils.cd(dir)
55 |
56 | elif command == 'ifconfig':
57 | utils.if_config()
58 |
59 | elif command.startswith("ping "):
60 | host = command[5:].strip()
61 | utils.ping(host)
62 |
63 | elif command.startswith("curl "):
64 | url = command[5:].strip()
65 | utils.curl(url)
66 |
67 | elif command.startswith('telnet '):
68 | tel = command[7:].strip()
69 | utils.telnet_launch(tel)
70 |
71 | elif command.startswith('mkdir '):
72 | dir = command[6:].strip()
73 | utils.mkdir(dir)
74 |
75 | elif command.startswith('rmdir '):
76 | dir = command[6:].strip()
77 | utils.rmdir(dir)
78 |
79 | elif command.startswith('rm '):
80 | file = command[3:].strip()
81 | utils.rm(file)
82 |
83 | elif command == 'sysinfo':
84 | utils.sysinfo()
85 |
86 | elif command == 'dspace':
87 | utils.get_storage()
88 |
89 | elif command == 'about':
90 | print(platform.platform())
91 |
92 | elif command == 'clock':
93 | print("CPU Clock:", machine.freq() // 1_000_000, "MHz")
94 |
95 | elif command.startswith('setclock '):
96 | clock = int(command[9:].strip())
97 | utils.overclock(clock)
98 |
99 | elif command == 'scan':
100 | utils.scan()
101 |
102 | elif command.startswith('clone '):
103 | try:
104 | args = command[6:].strip().split()
105 | url = args[0]
106 | filename = args[1] if len(args) > 1 else url.rsplit('/', 1)[-1]
107 | utils.download_file(url, filename)
108 | print(f"Downloading {filename} from {url}")
109 | except Exception as e:
110 | print("Download failed:", e)
111 |
112 | elif command.startswith("pmap "):
113 | parts = command.split()
114 | ip = parts[1]
115 | start = int(parts[2]) if len(parts) > 2 else 1
116 | end = int(parts[3]) if len(parts) > 3 else 1024
117 | utils.scan_ports(ip, start, end)
118 |
119 |
120 | elif command == 'clear':
121 | print('\033c', end='')
122 |
123 | elif command.startswith('blink'):
124 | utils.blink()
125 |
126 | elif command == 'reboot':
127 | print("Rebooting.")
128 | machine.reset()
129 |
130 | elif command == 'reset':
131 | print("Reseting")
132 | machine.soft_reset()
133 |
134 | elif command.startswith('read '):
135 | fName = command[4:].strip()
136 | utils.read(fName)
137 |
138 | elif command == 'ram':
139 | utils.get_mem()
140 |
141 | elif command == 'pwd':
142 | print(os.getcwd())
143 |
144 | elif command == 'temp':
145 | print(f"CPU Temp: {utils.read_temp():.2f} °C")
146 |
147 | elif command == 'freemem':
148 | utils.get_mem()
149 | gc.collect()
150 | print("After Garbage Collection: ")
151 | utils.get_mem()
152 |
153 |
154 | its += 1
155 |
156 | if its % 5 == 0 and its != 0:
157 | gc.collect()
158 |
159 | #else:
160 | #print("Unknown Command")
161 | except Exception as e:
162 | print("CLI ERROR: ",e)
163 |
164 | except KeyboardInterrupt:
165 | print()
166 | continue
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
--------------------------------------------------------------------------------
/pico-shell.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/patrickp02/PicoShell/dbf0e2c9bf92171050e5493af02615bf497a191c/pico-shell.png
--------------------------------------------------------------------------------
/telnet/utelnetserver.py:
--------------------------------------------------------------------------------
1 | import socket
2 | import network
3 | import uos
4 | import errno
5 | import gc
6 | from uio import IOBase
7 |
8 | last_client_socket = None
9 | server_socket = None
10 |
11 | class TelnetWrapper(IOBase):
12 | def __init__(self, socket):
13 | self.socket = socket
14 | self.discard_count = 0
15 | self._input_buffer = b""
16 |
17 | def readinto(self, b):
18 | readbytes = 0
19 | for i in range(len(b)):
20 | byte = 0
21 |
22 | while byte == 0:
23 | if not self._input_buffer:
24 | try:
25 | self._input_buffer = self.socket.recv(64)
26 | except OSError as e:
27 | if e.args and e.args[0] == errno.EAGAIN:
28 | return readbytes if readbytes else None
29 | raise
30 |
31 | if not self._input_buffer:
32 | return readbytes if readbytes else None
33 |
34 | byte = self._input_buffer[0]
35 | self._input_buffer = self._input_buffer[1:]
36 |
37 | if byte == 0xFF:
38 | self.discard_count = 2
39 | byte = 0
40 | elif self.discard_count > 0:
41 | self.discard_count -= 1
42 | byte = 0
43 | elif byte == 0:
44 | byte = 0 # null byte, discard
45 |
46 | b[i] = byte
47 | readbytes += 1
48 |
49 | return readbytes
50 |
51 | def write(self, data):
52 | mv = memoryview(data)
53 | while len(mv):
54 | try:
55 | sent = self.socket.write(mv)
56 | mv = mv[sent:]
57 | except OSError as e:
58 | if e.args and e.args[0] == errno.EAGAIN:
59 | continue
60 | raise
61 |
62 | def close(self):
63 | try:
64 | self.socket.close()
65 | except:
66 | pass
67 | self._input_buffer = b""
68 |
69 | def accept_telnet_connect(telnet_server):
70 | global last_client_socket
71 |
72 | uos.dupterm(None)
73 | if last_client_socket:
74 | try:
75 | last_client_socket.close()
76 | except:
77 | pass
78 | last_client_socket = None
79 |
80 | gc.collect()
81 |
82 | try:
83 | last_client_socket, remote_addr = telnet_server.accept()
84 | print("Telnet connection from:", remote_addr)
85 | last_client_socket.setblocking(False)
86 | uos.dupterm(TelnetWrapper(last_client_socket))
87 | print("[INFO] Telnet client accepted")
88 | print("[MEM] Free:", gc.mem_free(), "Used:", gc.mem_alloc())
89 | except Exception as e:
90 | print("[ERROR] Accept failed:", e)
91 |
92 | def stop():
93 | global server_socket, last_client_socket
94 | uos.dupterm(None)
95 |
96 | if server_socket:
97 | try:
98 | server_socket.close()
99 | except:
100 | pass
101 | server_socket = None
102 |
103 | if last_client_socket:
104 | try:
105 | last_client_socket.close()
106 | except:
107 | pass
108 | last_client_socket = None
109 |
110 | gc.collect()
111 | print("[INFO] Telnet server stopped")
112 | print("[MEM] Free:", gc.mem_free(), "Used:", gc.mem_alloc())
113 |
114 | def start(port=23):
115 | stop()
116 | global server_socket
117 |
118 | server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
119 | server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
120 |
121 | ai = socket.getaddrinfo("0.0.0.0", port)
122 | addr = ai[0][4]
123 |
124 | server_socket.bind(addr)
125 | server_socket.listen(1)
126 | server_socket.setsockopt(socket.SOL_SOCKET, 20, accept_telnet_connect)
127 |
128 | for i in (network.AP_IF, network.STA_IF):
129 | wlan = network.WLAN(i)
130 | if wlan.active():
131 | print("Telnet server started on {}:{}".format(wlan.ifconfig()[0], port))
132 |
--------------------------------------------------------------------------------
/utils.py:
--------------------------------------------------------------------------------
1 | import network
2 | import time
3 | import os
4 | import socket
5 | import urequests
6 | import gc
7 | from telnet import utelnetserver
8 | import ssl
9 | import machine
10 | from machine import Pin
11 |
12 |
13 | adc = machine.ADC(29)
14 | conversion_factor = 3.3 / 4095
15 | wlan = network.WLAN(network.STA_IF)
16 | led = Pin("LED", Pin.OUT)
17 | def auto_connect(ssid,password):
18 | wlan.active(True)
19 | wlan.connect(ssid,password)
20 |
21 | def read_wifi_config(filename):
22 | config = {}
23 | with open(filename, 'r') as file:
24 | for line in file:
25 | if '=' in line:
26 | key, value = line.strip().split('=', 1)
27 | config[key.strip()] = value.strip()
28 | return config['SSID'], config['PASSWORD']
29 | def overclock(clock):
30 | decide = input("WARNING! Overclocking can cause instability. Would you like to proceed?[Y/N]: ")
31 | if decide.lower() == 'y':
32 | if clock > 40 and clock < 260:
33 | machine.freq(clock * 1_000_000)
34 | print("Clock speed set to " + str(clock))
35 | else:
36 | if clock < 40:
37 | print("Clock speed is set too low!")
38 | else:
39 | print("Clock speed is set too high!")
40 |
41 | def get_storage():
42 | stats = os.statvfs("/")
43 | block_size = stats[0]
44 | total_blocks = stats[2]
45 | free_blocks = stats[3]
46 |
47 | total = (block_size * total_blocks) // 1024
48 | free = (block_size * free_blocks) // 1024
49 | used = total - free
50 |
51 | print("Storage:")
52 | print(f" Total: {total} KB")
53 | print(f" Used: {used} KB")
54 | print(f" Free: {free} KB")
55 |
56 | def getWifi():
57 | global wlan
58 | wlan.active(True)
59 |
60 | if wlan.isconnected():
61 | essid = wlan.config('essid')
62 | print("Connected to: ",essid)
63 | state = input(f"Would you like to disconnect from {essid}? [Y/N]: ")
64 |
65 | if state == 'Y' or state == 'y':
66 | wlan.disconnect()
67 | wlan.active(False) # Hard disables the Wi-Fi chip
68 | time.sleep(1) # Give it a sec to settle
69 | wlan.active(True)
70 | time.sleep(1)
71 | print("Disconnected!")
72 | return
73 |
74 | else:
75 | return
76 |
77 | while not wlan.isconnected():
78 | networks = wlan.scan()
79 | print("Available Networks:")
80 | for network in networks:
81 | print(f"SSID: {network[0]} Signal Strength: {network[3]}")
82 |
83 | essid = input("Enter the network name you would like to use: ")
84 | password = input("Enter the password for the network: ")
85 |
86 | if isinstance(password, str):
87 | wlan.active(True)
88 | wlan.connect(essid, password) # Attempt to connect
89 | else:
90 | print("Password must be a string!")
91 |
92 | # Wait until the device is connected
93 | start_time = time.ticks_ms() # Get the current time
94 | while not wlan.isconnected():
95 | print("Connecting...", end="") # Print without a new line
96 | time.sleep(1) # Wait for 1 second
97 | print(".", end="") # Add a dot every second
98 | timed = time.ticks_diff(time.ticks_ms(), start_time) # Check elapsed time
99 | if timed > 100000: # Timeout after 100 seconds
100 | print("Network error!")
101 | break
102 |
103 | # Once connected
104 | if wlan.isconnected():
105 | print("You're all connected!")
106 | print(wlan.ifconfig()) # Print the network configuration
107 |
108 | def cd(dir):
109 | try:
110 | os.chdir(dir)
111 | except OSError:
112 | print("Path does not exist!")
113 | print("Error: " + str(OSError))
114 |
115 | def ls():
116 |
117 | print(" ".join(os.listdir()))
118 | def run(script_name):
119 | try:
120 | # Check if the file exists
121 | if script_name in os.listdir():
122 | with open(script_name, "r") as file:
123 | script_content = file.read()
124 | code_obj = compile(script_content, script_name,'exec')
125 | exec(code_obj, {
126 | "__name__": "__main__",
127 | "input": input,
128 | "print": print,
129 | })
130 | del code_obj
131 |
132 | else:
133 | print(f"Error: {script_name} not found.")
134 | except Exception as e:
135 | print(f"Error running {script_name}: {e}")
136 |
137 | def if_config():
138 | print(" ".join(wlan.ifconfig()))
139 | if wlan.isconnected():
140 | print("Connected:", wlan.ifconfig())
141 | else:
142 | print("Not connected (IP config stale)")
143 |
144 | def read(fName):
145 | try:
146 | with open (fName) as f:
147 | print(f.read())
148 |
149 | except Exception as e:
150 | print("Error: ",e)
151 |
152 |
153 | def ping(host, count=4, timeout=1):
154 | try:
155 | # Resolve host to get address info
156 | addr_info = socket.getaddrinfo(host, 80)
157 | addr = addr_info[0][-1][0] # Extract the IP address from the tuple
158 | print(f"Pinging {host} ({addr}) with {count} packets:")
159 |
160 | for i in range(count):
161 | start_time = time.ticks_ms()
162 |
163 |
164 | s = socket.socket()
165 | s.settimeout(timeout)
166 |
167 | try:
168 | s.connect((addr, 80))
169 | end_time = time.ticks_ms()
170 | elapsed_time = time.ticks_diff(end_time, start_time)
171 | print(f"Reply from {addr}: time={elapsed_time}ms")
172 | except OSError:
173 | print(f"Request timed out for {host}")
174 |
175 | s.close()
176 | time.sleep(1)
177 |
178 | except Exception as e:
179 | print(f"Error: {e}")
180 |
181 | def curl(url):
182 | try:
183 | response = urequests.get(url)
184 | print(response.text)
185 | response.close()
186 | except Exception as e:
187 | print("Error: " , e)
188 | finally:
189 | gc.collect()
190 |
191 | def telnet_launch(tel):
192 | if tel == 'launch':
193 | utelnetserver.start()
194 | if tel == 'stop':
195 | utelnetserver.stop()
196 | gc.collect()
197 |
198 | def download_file(url, filename):
199 | _, _, host, path = url.split('/', 3)
200 | addr = socket.getaddrinfo(host, 443)[0][-1]
201 |
202 | s = socket.socket()
203 | s.connect(addr)
204 | s = ssl.wrap_socket(s, server_hostname=host)
205 |
206 | req = f"GET /{path} HTTP/1.0\r\nHost: {host}\r\n\r\n"
207 | s.write(req.encode())
208 |
209 | header_passed = False
210 | with open(filename, 'w') as f:
211 | while True:
212 | data = s.read(1024)
213 | if data:
214 | content = data.decode()
215 | if not header_passed:
216 | if "\r\n\r\n" in content:
217 | content = content.split("\r\n\r\n", 1)[1]
218 | header_passed = True
219 | else:
220 | continue
221 | f.write(content)
222 | else:
223 | break
224 | s.close()
225 |
226 | def scan():
227 | try:
228 | networks = wlan.scan()
229 | print("Available Networks:")
230 | for network in networks:
231 | print(f"SSID: {network[0]} Signal Strength: {network[3]}")
232 | except Exception as e:
233 | print("Error: ", e)
234 |
235 | def scan_ports(ip, start=1, end=1024):
236 | print(f"Scanning {ip} from port {start} to {end}...")
237 | found = False
238 | for port in range(start, end + 1):
239 | try:
240 | s = socket.socket()
241 | s.settimeout(0.2)
242 | s.connect((ip, port))
243 | print(f"Port {port}: OPEN")
244 | found = True
245 | s.close()
246 | except:
247 | pass
248 | if not found:
249 | print("No open ports detected.")
250 |
251 | def blink(times=3, delay=0.2):
252 | for _ in range(times):
253 | led.toggle()
254 | time.sleep(delay)
255 | led.toggle()
256 | time.sleep(delay)
257 |
258 | def read_temp():
259 | try:
260 | raw = adc.read_u16() * conversion_factor
261 | temp = (27 - (raw - 0.706) / 0.001721) / 10
262 | return temp
263 | except Exception as e:
264 | print("ERROR:",e)
265 | def get_mem():
266 | print("Free:", gc.mem_free()/1024, "kilobytes")
267 | print("Used:", gc.mem_alloc()/1024, "kilobytes")
268 | print("Total:", (gc.mem_alloc() + gc.mem_free())/1024, "kilobytes")
269 |
270 | def mkdir(dir):os.mkdir(dir)
271 |
272 | def rmdir(dir):os.rmdir(dir)
273 |
274 | def rm(file):os.remove(file)
275 |
276 | def sysinfo():print(" ".join(os.uname()))
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
--------------------------------------------------------------------------------