-
Notifications
You must be signed in to change notification settings - Fork 105
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add ESP32 to supported devices with basic type hints #114
Open
Gor-Ren
wants to merge
2
commits into
JetBrains:master
Choose a base branch
from
Gor-Ren:support-esp32
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 1 commit
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
51 changes: 51 additions & 0 deletions
51
src/main/kotlin/com/jetbrains/micropython/devices/Esp32DeviceProvider.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
package com.jetbrains.micropython.devices | ||
|
||
import com.intellij.execution.configurations.CommandLineState | ||
import com.intellij.execution.configurations.GeneralCommandLine | ||
import com.intellij.execution.process.OSProcessHandler | ||
import com.intellij.execution.runners.ExecutionEnvironment | ||
import com.intellij.openapi.projectRoots.Sdk | ||
import com.jetbrains.micropython.run.MicroPythonRunConfiguration | ||
import com.jetbrains.micropython.run.getMicroUploadCommand | ||
import com.jetbrains.micropython.settings.MicroPythonTypeHints | ||
import com.jetbrains.micropython.settings.MicroPythonUsbId | ||
import com.jetbrains.python.packaging.PyPackageManager | ||
import com.jetbrains.python.packaging.PyRequirement | ||
|
||
/** | ||
* @author Gor-Ren | ||
*/ | ||
class Esp32DeviceProvider : MicroPythonDeviceProvider { | ||
override val persistentName: String | ||
get() = "ESP32" | ||
|
||
override val documentationURL: String | ||
get() = "https://github.com/vlasovskikh/intellij-micropython/wiki/ESP32" // FIXME: add wiki page | ||
|
||
override val usbIds: List<MicroPythonUsbId> | ||
get() = listOf(MicroPythonUsbId(0x1A86, 0x7523), | ||
MicroPythonUsbId(0x10C4, 0xEA60), | ||
MicroPythonUsbId(0x0403, 0x6001)) | ||
|
||
override val typeHints: MicroPythonTypeHints by lazy { | ||
MicroPythonTypeHints(listOf("stdlib", "micropython", "esp32")) | ||
} | ||
|
||
override fun getPackageRequirements(sdk: Sdk): List<PyRequirement> { | ||
val manager = PyPackageManager.getInstance(sdk) | ||
return manager.parseRequirements("""|pyserial>=3.3,<4.0 | ||
|docopt>=0.6.2,<0.7 | ||
|adafruit-ampy>=1.0.5,<1.1""".trimMargin()) | ||
} | ||
|
||
override fun getRunCommandLineState(configuration: MicroPythonRunConfiguration, | ||
environment: ExecutionEnvironment): CommandLineState? { | ||
val module = configuration.module ?: return null | ||
val command = getMicroUploadCommand(configuration.path, module) ?: return null | ||
|
||
return object : CommandLineState(environment) { | ||
override fun startProcess() = | ||
OSProcessHandler(GeneralCommandLine(command)) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
|
||
from typing import Optional | ||
|
||
def sleep_type(sleep_type: Optional[int]) -> Optional[int]: | ||
""" | ||
Get or set the sleep type. | ||
|
||
If the sleep_type parameter is provided, sets the sleep type to its value. | ||
If the function is called without parameters, returns the current sleep type. | ||
|
||
The possible sleep types are defined as constants: | ||
|
||
* ``SLEEP_NONE`` – all functions enabled,\n | ||
* ``SLEEP_MODEM`` – modem sleep, shuts down the WiFi Modem circuit.\n | ||
* ``SLEEP_LIGHT`` – light sleep, shuts down the WiFi Modem circuit and suspends the processor periodically.\n | ||
The system enters the set sleep mode automatically when possible. | ||
|
||
:param sleep_type: Sleep type. | ||
:type sleep_type: int | ||
:return: Current sleep type | ||
:rtype: int | ||
""" | ||
|
||
def deepsleep(time: int = 0) -> None: | ||
""" | ||
Enter deep sleep. | ||
|
||
The whole module powers down, except for the RTC clock circuit, which can | ||
be used to restart the module after the specified time if the pin 16 is | ||
connected to the reset pin. Otherwise the module will sleep until manually reset. | ||
|
||
:param time: Amount of time in milliseconds to sleep. | ||
""" | ||
|
||
def set_native_code_location(start: Optional[int], length: Optional[int]) -> None: | ||
""" | ||
Set the location that native code will be placed for execution after it is | ||
compiled. Native code is emitted when the ``@micropython.native``, ``@micropython.viper`` | ||
and ``@micropython.asm_xtensa`` decorators are applied to a function. The | ||
ESP8266 must execute code from either iRAM or the lower 1MByte of flash | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks like a missed comment update. Still referring to ESP8266. Not ESP32. |
||
(which is memory mapped), and this function controls the location. | ||
|
||
If start and length are both **None** then the native code location is | ||
set to the unused portion of memory at the end of the iRAM1 region. The | ||
size of this unused portion depends on the firmware and is typically | ||
quite small (around 500 bytes), and is enough to store a few very small | ||
functions. The advantage of using this iRAM1 region is that it does not | ||
get worn out by writing to it. | ||
|
||
If neither start nor length are None then they should be integers. start | ||
should specify the byte offset from the beginning of the flash at which | ||
native code should be stored. length specifies how many bytes of flash | ||
from start can be used to store native code. start and length should be | ||
multiples of the sector size (being 4096 bytes). The flash will be | ||
automatically erased before writing to it so be sure to use a region of | ||
flash that is not otherwise used, for example by the firmware or the filesystem. | ||
|
||
When using the flash to store native code *start*+*length* must be less | ||
than or equal to 1MByte. Note that the flash can be worn out if repeated | ||
erasures (and writes) are made so use this feature sparingly. In particular, | ||
native code needs to be recompiled and rewritten to flash on each boot | ||
(including wake from deepsleep). | ||
|
||
In both cases above, using iRAM1 or flash, if there is no more room left in | ||
the specified region then the use of a native decorator on a function will | ||
lead to ``MemoryError`` exception being raised during compilation of that function. | ||
|
||
:param start: Start of native code region. | ||
:param length: End of native code region. | ||
""" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,203 @@ | ||
"""network configuration | ||
|
||
This module provides network drivers and routing configuration. To use this | ||
module, a MicroPython variant/build with network capabilities must be installed. | ||
Network drivers for specific hardware are available within this module and are | ||
used to configure hardware network interface(s). Network services provided | ||
by configured interfaces are then available for use via the :mod:`usocket` | ||
module. | ||
|
||
For example:: | ||
|
||
# connect/ show IP config a specific network interface | ||
# see below for examples of specific drivers | ||
import network | ||
import utime | ||
nic = network.Driver(...) | ||
if not nic.isconnected(): | ||
nic.connect() | ||
print("Waiting for connection...") | ||
while not nic.isconnected(): | ||
utime.sleep(1) | ||
print(nic.ifconfig()) | ||
|
||
# now use usocket as usual | ||
import usocket as socket | ||
addr = socket.getaddrinfo('micropython.org', 80)[0][-1] | ||
s = socket.socket() | ||
s.connect(addr) | ||
s.send(b'GET / HTTP/1.1\r\nHost: micropython.org\r\n\r\n') | ||
data = s.recv(1000) | ||
s.close() | ||
""" | ||
|
||
from typing import overload, Optional, List, Tuple, Union, Any | ||
|
||
|
||
@overload | ||
def phy_mode() -> int: | ||
"""Get the PHY mode.""" | ||
... | ||
|
||
|
||
@overload | ||
def phy_mode(mode: int) -> None: | ||
"""Set the PHY mode. | ||
|
||
The possible modes are defined as constants: | ||
* ``MODE_11B`` -- IEEE 802.11b, | ||
* ``MODE_11G`` -- IEEE 802.11g, | ||
* ``MODE_11N`` -- IEEE 802.11n. | ||
""" | ||
... | ||
|
||
|
||
class WLAN: | ||
def __init__(self, interface_id: int) -> None: | ||
"""Create a WLAN network interface object. Supported interfaces are | ||
``network.STA_IF`` (station aka client, connects to upstream WiFi access | ||
points) and ``network.AP_IF`` (access point, allows other WiFi clients to | ||
connect). Availability of the methods below depends on interface type. | ||
For example, only STA interface may `connect()` to an access point. | ||
""" | ||
... | ||
|
||
@overload | ||
def active(self) -> bool: | ||
"""Query current state of the interface.""" | ||
... | ||
|
||
@overload | ||
def active(self, is_active: bool) -> None: | ||
"""Activate ("up") or deactivate ("down") network interface.""" | ||
... | ||
|
||
def connect(self, ssid: Optional[Union[bytes, str]] = None, | ||
password: Optional[Union[bytes, str]] = None, *, | ||
bssid: Optional[Union[bytes, str]] = None) -> None: | ||
"""Connect to the specified wireless network, using the specified password. | ||
If *bssid* is given then the connection will be restricted to the | ||
access-point with that MAC address (the *ssid* must also be specified | ||
in this case). | ||
""" | ||
... | ||
|
||
def disconnect(self) -> None: | ||
"""Disconnect from the currently connected wireless network.""" | ||
... | ||
|
||
def scan(self) -> List[Tuple[bytes, bytes, int, int, int, int]]: | ||
"""Scan for the available wireless networks. | ||
|
||
Scanning is only possible on STA interface. Returns list of tuples with | ||
the information about WiFi access points: | ||
|
||
(ssid, bssid, channel, RSSI, authmode, hidden) | ||
|
||
*bssid* is hardware address of an access point, in binary form, returned as | ||
bytes object. You can use `ubinascii.hexlify()` to convert it to ASCII form. | ||
|
||
There are five values for authmode: | ||
|
||
* 0 -- open | ||
* 1 -- WEP | ||
* 2 -- WPA-PSK | ||
* 3 -- WPA2-PSK | ||
* 4 -- WPA/WPA2-PSK | ||
|
||
and two for hidden: | ||
|
||
* 0 -- visible | ||
* 1 -- hidden | ||
""" | ||
... | ||
|
||
def status(self) -> int: | ||
"""Return the current status of the wireless connection. | ||
|
||
The possible statuses are defined as constants: | ||
|
||
* ``STAT_IDLE`` -- no connection and no activity, | ||
* ``STAT_CONNECTING`` -- connecting in progress, | ||
* ``STAT_WRONG_PASSWORD`` -- failed due to incorrect password, | ||
* ``STAT_NO_AP_FOUND`` -- failed because no access point replied, | ||
* ``STAT_CONNECT_FAIL`` -- failed due to other problems, | ||
* ``STAT_GOT_IP`` -- connection successful. | ||
""" | ||
... | ||
|
||
def isconnected(self) -> bool: | ||
"""In case of STA mode, returns ``True`` if connected to a WiFi access | ||
point and has a valid IP address. In AP mode returns ``True`` when a | ||
station is connected. Returns ``False`` otherwise. | ||
""" | ||
... | ||
|
||
@overload | ||
def ifconfig(self) -> Tuple[str, str, str, str]: | ||
"""Get IP-level network interface parameters: IP address, subnet mask, | ||
gateway and DNS server. | ||
""" | ||
... | ||
|
||
@overload | ||
def ifconfig(self, ip: str, subnet: str, gateway: str, dns: str) -> None: | ||
"""Get/set IP-level network interface parameters: IP address, subnet mask, | ||
gateway and DNS server. | ||
""" | ||
... | ||
|
||
@overload | ||
def config(self, param: str) -> Any: | ||
"""Get general network interface parameters.""" | ||
... | ||
|
||
@overload | ||
def config(self, **kwargs: Any) -> None: | ||
"""Get or set general network interface parameters. These methods allow to work | ||
with additional parameters beyond standard IP configuration (as dealt with by | ||
`wlan.ifconfig()`). These include network-specific and hardware-specific | ||
parameters. For setting parameters, keyword argument syntax should be used, | ||
multiple parameters can be set at once. For querying, parameters name should | ||
be quoted as a string, and only one parameter can be queries at time:: | ||
|
||
# Set WiFi access point name (formally known as ESSID) and WiFi channel | ||
ap.config(essid='My AP', channel=11) | ||
# Query params one by one | ||
print(ap.config('essid')) | ||
print(ap.config('channel')) | ||
|
||
Following are commonly supported parameters (availability of a specific parameter | ||
depends on network technology type, driver, and `MicroPython port`). | ||
|
||
============= =========== | ||
Parameter Description | ||
============= =========== | ||
mac MAC address (bytes) | ||
essid WiFi access point name (string) | ||
channel WiFi channel (integer) | ||
hidden Whether ESSID is hidden (boolean) | ||
authmode Authentication mode supported (enumeration, see module constants) | ||
password Access password (string) | ||
dhcp_hostname The DHCP hostname to use | ||
============= =========== | ||
""" | ||
... | ||
|
||
|
||
STA_IF: int | ||
AP_IF: int | ||
|
||
|
||
STAT_IDLE: int | ||
STAT_CONNECTING: int | ||
STAT_WRONG_PASSWORD: int | ||
STAT_NO_AP_FOUND: int | ||
STAT_CONNECT_FAIL: int | ||
STAT_GOT_IP: int | ||
|
||
|
||
MODE_11B: int | ||
MODE_11G: int | ||
MODE_11N: int | ||
|
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These are copied from the ESP8266.
To find the values for an ESP32, I connected MCUs by USB and ran
$ cat /sys/bus/usb-serial/devices/ttyUSB0/../uevent
. I tested with an ESP8266 and an ESP32 and both outputPRODUCT=10c4/ea60/100
. I was a bit surprised - I expected them to be different.PRODUCT=10c4/ea60/100
corresponds to the second element in this list. Auto-detect of my ESP32 subsequently worked. Shall we keep all the values copied from ESP8266 the same, then?