Skip to content

Commit

Permalink
Remove esp32 specific code from network
Browse files Browse the repository at this point in the history
Also purge documentation of this feature.

Signed-off-by: Paul Guyot <[email protected]>
  • Loading branch information
pguyot committed Oct 7, 2023
1 parent 61f4b72 commit 2eb5858
Show file tree
Hide file tree
Showing 3 changed files with 10 additions and 70 deletions.
2 changes: 2 additions & 0 deletions UPDATING.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,5 @@
`v0.6.0-alpha.0` cannot work on top of latest version.
- Address (offset) of programs for Pico was changed from 0x100A0000 to 0x10100000. UF2
binaries need to be rebuilt with the proper offset using `uf2tool`.
- On ESP32, SSID and PSK stored in NVS are no longer read by network module. Applications
must fetch the values and pass them to `network:start/1` or `network:start_link/1`.
39 changes: 7 additions & 32 deletions doc/src/network-programming-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,19 @@

# Network Programming Guide

One of the exciting features of the ESP32 is its support for WiFi networking, allowing ESP32 micro-controllers to communicate with the outside world over common IP networking protocols, such as TCP or IDP. The ESP32 and ISF SDK supports configuring an ESP32 in station mode (STA), whereby the device connects to an existing access point, as well as "softAP" mode (AP), whereby it functions as an access point, to which other stations can connect. The ESP32 also supports a combined STA+softAP mode, which allows the device to function in both STA and softAP mode simultaneously.
One of the exciting features of the ESP32 and the Pico-W is their support for WiFi networking, allowing ESP32 and Pico-W micro-controllers to communicate with the outside world over common IP networking protocols, such as TCP or IDP. The ESP32 and the Pico-W can be configured in station mode (STA), whereby the devices connect to an existing access point, as well as "softAP" mode (AP), whereby they function as an access point, to which other stations can connect. The ESP32 also supports a combined STA+softAP mode, which allows the device to function in both STA and softAP mode simultaneously.

AtomVM provides an Erlang API interface for interacting with the WiFi networking layer on ESP32 devices, providing support for configuring your ESP32 device in STA mode, AP mode, or a combined STA+AP mode, allowing Erlang/Elixir applications to send and receive data from other devices on a network. This interface is encapsulated in the `network` module, which implements a simple interface for connecting to existing WiFi networks or for functioning as a WiFi access point.
AtomVM provides an Erlang API interface for interacting with the WiFi networking layer on ESP32 and Pico-W devices, providing support for configuring your ESP32 or Pico-W device in STA mode, AP mode, or a combined STA+AP mode, allowing Erlang/Elixir applications to send and receive data from other devices on a network. This interface is encapsulated in the `network` module, which implements a simple interface for connecting to existing WiFi networks or for functioning as a WiFi access point. The same `network` module is used for both the ESP32 and the Pico-W.

Once the network has been set up (in STA or AP mode), AtomVM can use various socket interfaces to interact with the socket layer to create a client or server application. For example, AtomVM supports the `gen_udp` and `gen_tcp` APIs, while AtomVM extensions may support HTTP, MQTT, and other protocols built over low-level networking interfaces.
Once the network has been set up (in STA or AP mode), AtomVM can use various socket interfaces to interact with the socket layer to create a client or server application. For example, on ESP32, AtomVM supports the `gen_udp` and `gen_tcp` APIs, while AtomVM extensions may support HTTP, MQTT, and other protocols built over low-level networking interfaces.

The AtomVM networking API leverages callback functions, allowing applications to be responsive to changes in the underlying network, which can frequently occur in embedded applications, where devices can easily lose and then regain network connectivity. In such cases, it is important for applications to be resilient to changes in network availability, by closing or re-opening socket connections in response to disconnections and re-connections in the underlying network.

This document describes the basic design of the AtomVM network interfaces, and how to interact programmatically with it.

## Station (STA) mode

In STA mode, the ESP32 connects to an existing WiFi network.
In STA mode, the ESP32 or the Pico-W connect to an existing WiFi network.

In this case, the input configuration should be a properties list containing a tuple of the form `{sta, <sta-properties>}`, where `<sta-properties>` is a property list containing configuration properties for the device in station mode.

Expand All @@ -27,8 +27,6 @@ The `<sta-properties>` property list should contain the following entries:
* `{ssid, string() | binary()}` The SSID to which the device should connect.
* `{psk, string() | binary()}` The password required to authenticate to the network, if required.

> Note that the station mode SSID and password _may_ be stored in non-volatile storage, in which case these parameters may be skipped. See the "NVS Credentials" section below, for more information about using non-volatile storage to store credentials that persist across device reboots.
The `network:start/1` will immediately return `{ok, Pid}`, where `Pid` is the process ID of the network server instance, if the network was properly initialized, or `{error, Reason}`, if there was an error in configuration. However, the application may want to wait for the device to connect to the target network and obtain an IP address, for example, before starting clients or services that require network access.

Applications can specify callback functions, which get triggered as events emerge from the network layer, including connection to and disconnection from the target network, as well as IP address acquisition.
Expand All @@ -43,7 +41,7 @@ Callback functions can be specified by the following configuration parameters:
Callback functions are optional, but are highly recommended for building robust WiFi applications. The return value from callback functions is ignored, and AtomVM provides no guarantees about the execution context (i.e., BEAM process) in which these functions are invoked.

In addition, the following optional parameters can be specified to configure the AP network:
In addition, the following optional parameters can be specified to configure the AP network (ESP32 only):

* `{dhcp_hostname, string()|binary()}` The DHCP hostname as which the device should register (`<<"atomvm-<hexmac>">>`, where `<hexmac>` is the hexadecimal representation of the factory-assigned MAC address of the device).

Expand Down Expand Up @@ -111,8 +109,6 @@ If the SSID is omitted in configuration, the SSID name `atomvm-<hexmac>` will be

If the password is omitted, then an _open network_ will be created, and a warning will be printed to the console. Otherwise, the AP network will be started using WPA+WPA2 authentication.

> Note that the station mode SSID and password _may_ be stored in non-volatile storage, in which case these parameters may be skipped. See the "NVS Credentials" section below, for more information about using non-volatile storage to store credentials that persist across device reboots.
The `network:start/1` will immediately return `{ok, Pid}`, where `Pid` is the process id of the network server, if the network was properly initialized, or `{error, Reason}`, if there was an error in configuration. However, the application may want to wait for the device to to be ready to accept connections from other devices, or to be notified when other devices connect to this AP.

Applications can specify callback functions, which get triggered as events emerge from the network layer, including when a station connects or disconnects from the AP, as well as when a station is assigned an IP address.
Expand Down Expand Up @@ -218,28 +214,7 @@ where the `sntp_synchronized/1` function is defined as:

It can become tiresome to enter an SSID and password for every application, and in general it is bad security practice to hard-wire WiFi credentials in your application source code.

You may instead store an STA or AP SSID and PSK in non-volatile storage (NVS) on and ESP32 device under the `atomvm` namespace. The following entries may be specified in non-volatile storage:

| namespace | mode | key | type | value |
|-----------|------|----------|--------|-------|
| `atomvm` | STA | `sta_ssid` | `binary()` | Station ID |
| `atomvm` | STA | `sta_psk` | `binary()` | Station password (if applicable) |
| `atomvm` | AP | `ap_ssid` | `binary()` | Access Point ID |
| `atomvm` | AP | `ap_psk` | `binary()` | Access Point password (if applicable) |

If set in NVS storage, you may remove the corresponding `ssid` and `psk` parameters from the configuration used to initialize the network, and the SSID and PSK configured in NVS will be used, instead. An SSID or PSK defined explicitly in configuration will override any values in NVS.

You can set these credentials once, as follows:

esp:nvs_put_binary(atomvm, sta_ssid, <<"myssid">>).
esp:nvs_put_binary(atomvm, sta_psk, <<"mypsk">>).

or

esp:nvs_put_binary(atomvm, ap_ssid, <<"myssid">>).
esp:nvs_put_binary(atomvm, ap_psk, <<"mypsk">>).

With these settings, you can run ESP programs that initialize the network without configuring your SSID and PSK explicitly in source code.
You may instead store an STA or AP SSID and PSK in non-volatile storage (NVS) on and ESP32 device under the `atomvm` namespace.

> Note. Credentials are stored un-encrypted and in plaintext and should not be considered secure. Future versions may use encrypted NVS storage.
Expand All @@ -249,4 +224,4 @@ To stop the network and free any resources in use, issue the `stop/0` function:

network:stop().

> Note. This function is currently not well tested.
> Note. Stop is currently unimplemented.
39 changes: 1 addition & 38 deletions libs/eavmlib/src/network.erl
Original file line number Diff line number Diff line change
Expand Up @@ -259,8 +259,7 @@ init(Config) ->
handle_call(start, From, #state{config = Config} = State) ->
Port = get_port(),
Ref = make_ref(),
DriverConfig = get_driver_config(Config),
Port ! {self(), Ref, {start, DriverConfig}},
Port ! {self(), Ref, {start, Config}},
wait_start_reply(Ref, From, Port, State);
handle_call(_Msg, _From, State) ->
{reply, {error, unknown_message}, State}.
Expand Down Expand Up @@ -319,42 +318,6 @@ terminate(_Reason, _State) ->
%% Internal operations
%%

%% @private
get_driver_config(Config) ->
Config1 =
case proplists:get_value(sta, Config) of
undefined ->
Config;
StaConfig ->
NewStaConfig1 = maybe_add_nvs_entry(ssid, StaConfig, sta_ssid),
NewStaConfig2 = maybe_add_nvs_entry(psk, NewStaConfig1, sta_psk),
[{sta, NewStaConfig2} | lists:keydelete(sta, 1, Config)]
end,
Config2 =
case proplists:get_value(ap, Config1) of
undefined ->
Config1;
ApConfig ->
NewApConfig1 = maybe_add_nvs_entry(ssid, ApConfig, ap_ssid),
NewApConfig2 = maybe_add_nvs_entry(psk, NewApConfig1, ap_psk),
[{ap, NewApConfig2} | lists:keydelete(ap, 1, Config1)]
end,
Config2.

%% @private
maybe_add_nvs_entry(Key, List, NVSKey) ->
case proplists:get_value(Key, List) of
undefined ->
case esp:nvs_get_binary(atomvm, NVSKey) of
undefined ->
List;
NVSValue ->
[{Key, NVSValue} | List]
end;
_Value ->
List
end.

%% @private
maybe_sta_connected_callback(Config) ->
maybe_callback0(connected, proplists:get_value(sta, Config)).
Expand Down

0 comments on commit 2eb5858

Please sign in to comment.