diff --git a/docs/_images/cellular_tower.svg b/docs/_images/cellular_tower.svg
new file mode 100644
index 00000000..1e2f3858
--- /dev/null
+++ b/docs/_images/cellular_tower.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/docs/_images/walter.png b/docs/_images/walter.png
new file mode 100644
index 00000000..5e0451e2
Binary files /dev/null and b/docs/_images/walter.png differ
diff --git a/docs/tutorials/index.mdx b/docs/tutorials/index.mdx
index bb2dc139..86c7fc79 100644
--- a/docs/tutorials/index.mdx
+++ b/docs/tutorials/index.mdx
@@ -29,6 +29,7 @@ import Shushing from "../_images/shushing_face.svg";
import Supabase from "../_images/supabase_logo.svg";
import AwsIotCore from "../_images/aws_iot_core.png";
import Ota from "../_images/ota.png";
+import CellTower from "../_images/cellular_tower.svg";
# Tutorials
@@ -307,6 +308,18 @@ Connect to a BLE device.
## Network
Get to know about how to use the network capabilities of your device.
+
+
+
+
+Connect to the internet using a cellular modem.
+
+
+
+
+## Prerequisites
+We assume that you have set up your development environment as described
+in [the IDE tutorial](../../setup/ide).
+
+We also assume that you have flashed your device with Jaguar and that
+you are familiar with running Toit programs on it.
+If not, have a look at the [Hello world](../../setup/firstprogram) tutorial.
+
+Note that the Walter device is an ESP32-S3 board, which requires the
+`--chip=esp32s3` flag when flashing.
+
+In later sections we will refer to [containers](../containers) and
+[services](../containers/services), but these are not strictly necessary.
+
+We will use HTTP to fetch data from the internet. There are
+[multiple](./http) [tutorials](./http-server) on this topic, but you
+should be able to follow this tutorial without having read them.
+
+## Packages
+Cellular functionality is not part of the core libraries and must be
+imported as a package. See the [packages](../../setup/packages)
+tutorial for details.
+
+As of writing, all drivers for cellular modems are in the
+[cellular](https://pkg.toit.io/package/github.com%2Ftoitware%2Fcellular@v2)
+package.
+
+To install it, run the following command:
+
+``` shell
+jag pkg install github.com/toitware/cellular@v2
+```
+
+We will use the
+[http](https://pkg.toit.io/package/github.com%2Ftoitlang%2Fpkg-http@v2)
+and the [certificate-roots](https://pkg.toit.io/package/github.com%2Ftoitware%2Ftoit-cert-roots@v1)
+packages to fetch data from the internet.
+
+``` shell
+jag pkg install github.com/toitlang/pkg-http@v2
+jag pkg install github.com/toitware/toit-cert-roots@v1
+```
+
+## Code
+
+Start a new Toit program `walter.toit` and watch it with Jaguar.
+
+``` toit
+import cellular.modules.sequans.monarch
+import http
+import encoding.json
+import net
+import net.cellular
+import certificate-roots
+
+RX ::= 14
+TX ::= 48
+RTS ::= 21
+CTS ::= 47
+RESET ::= 45
+POWER ::= 46
+BAUD ::= 115200
+
+main:
+ // Start the monarch driver/provider.
+ task --background::
+ monarch.main
+
+ // Establish the connection to the network.
+ network := cellular.open --name="gm02sp" {
+ cellular.CONFIG-UART-RX: RX,
+ cellular.CONFIG-UART-TX: TX,
+ cellular.CONFIG-UART-CTS: CTS,
+ cellular.CONFIG-UART-RTS: RTS,
+ cellular.CONFIG-RESET: [RESET, cellular.CONFIG-ACTIVE-LOW],
+ cellular.CONFIG-POWER: POWER,
+ cellular.CONFIG-UART-BAUD-RATE: BAUD,
+ }
+
+ try:
+ do-network-things network
+ finally:
+ network.close
+```
+
+The constants for the Walter board can be found in its
+[datasheet](https://www.quickspot.io/datasheet/walter_datasheet_v0.4.pdf). The
+modem constants are specificed in section 4.1.2 ("Internal Pins").
+
+Even though the modem isn't a "Monarch", but a "GM02SP", we can use the `monarch` driver.
+Both are manufactured by Sequans, and use similar AT commands. Eventually, there might be
+a more specialized driver for the GM02SP.
+
+The `monarch.main` function installs the driver as a provider so that other code
+can use it through a service. We happen to use it from the same process, but that's
+not a requirement. In fact, we will see later how the provider can be started in
+a different container, so that different programs can have access to the internet
+at the same time.
+
+Once the provider is running in the background, we simply use the `cellular.open`
+function to establish a connection to the network. It will return a `net.Client`
+object that we can pass to code that needs to use the network.
+
+For example, the `do-network-things` function could look as follows:
+
+``` toit
+do-network-things network/net.Client:
+ client := http.Client.tls network
+ --root-certificates=[certificate-roots.GTS-ROOT-R1]
+ request := client.get --uri="https://official-joke-api.appspot.com/random_joke"
+ decoded := json.decode-stream request.body
+ print decoded["setup"]
+ print decoded["punchline"]
+```
+
+## Container
+In our first iteration the cellular provider was started in the same
+container as the rest of the code. This is not ideal, as the cellular
+connection is then not available to other containers.
+
+We can fix this, by installing the cellular provider in its own container.
+
+Create a new file `cellular.toit` with the following content:
+
+``` toit
+import net.cellular
+import cellular.modules.sequans.monarch
+
+RX ::= 14
+TX ::= 48
+RTS ::= 21
+CTS ::= 47
+RESET ::= 45
+POWER ::= 46
+BAUD ::= 115200
+
+class WalterCellularProvider extends monarch.MonarchService:
+ connect client/int config/Map? -> List:
+ if not config or config.is-empty:
+ config = {
+ cellular.CONFIG-UART-RX: RX,
+ cellular.CONFIG-UART-TX: TX,
+ cellular.CONFIG-UART-CTS: CTS,
+ cellular.CONFIG-UART-RTS: RTS,
+ cellular.CONFIG-RESET: [RESET, cellular.CONFIG-ACTIVE-LOW],
+ cellular.CONFIG-POWER: POWER,
+ cellular.CONFIG-UART-BAUD-RATE: BAUD,
+ }
+ return super client config
+
+main:
+ provider := WalterCellularProvider
+ provider.install
+```
+
+The `WalterCellularProvider` extends the `MonarchService` (which was
+installed as part of the `monarch.main` call in the previous section), and
+overrides the `connect` method to use the constants for the Walter board.
+
+Note that the name `MonarchService` is a bit misleading, as it is actually
+a provider (extending the `CellularServiceProvider` class).
+
+The `main` function then installs the provider, so that containers
+can use it.
+
+We can now install this container on the device:
+
+``` shell
+jag container install cellular cellular.toit
+```
+
+Other containers can now use the cellular provider.
+
+For example, create, and watch the following `cellular-user.toit` program:
+
+``` toit
+import net
+import net.cellular
+
+do-network-things network/net.Client:
+ ...
+
+main:
+ network := cellular.open --name="walter" {:}
+
+ try:
+ do-network-things network
+ finally:
+ network.close
+```
+
+The `do-network-things` function could be the same as in the previous
+section (in which case you will have to add a few more imports).
+
+Note that multiple containers can call `cellular.open` at the same time and
+access the internet concurrently.
diff --git a/tools/package.lock b/tools/package.lock
index 200a64f6..8505d2e2 100644
--- a/tools/package.lock
+++ b/tools/package.lock
@@ -1,6 +1,7 @@
-sdk: ^2.0.0-alpha.91
+sdk: ^2.0.0-alpha.108
prefixes:
bme280: bme280-driver
+ cellular: cellular
certificate_roots: toit-cert-roots
cli: pkg-cli
dhtxx: toit-dhtxx
@@ -25,6 +26,11 @@ packages:
name: bme280
version: 1.0.0
hash: 65b88ac19a5e2b48627a2dbae6d7757ae45c502c
+ cellular:
+ url: github.com/toitware/cellular
+ name: cellular
+ version: 2.1.10
+ hash: a2b641e2da596ac1fd58b5fd5ce5e26d5e501c35
mqtt:
url: github.com/toitware/mqtt
name: mqtt
diff --git a/tools/package.yaml b/tools/package.yaml
index 7d578eb9..0f90137b 100644
--- a/tools/package.yaml
+++ b/tools/package.yaml
@@ -2,6 +2,9 @@ dependencies:
bme280:
url: github.com/toitware/bme280-driver
version: ^1.0.0
+ cellular:
+ url: github.com/toitware/cellular
+ version: ^2.1.10
certificate_roots:
url: github.com/toitware/toit-cert-roots
version: ^1.6.1
diff --git a/tools/run_snippets.toit b/tools/run_snippets.toit
index 99a2e338..75576b59 100644
--- a/tools/run_snippets.toit
+++ b/tools/run_snippets.toit
@@ -40,6 +40,7 @@ THINGS-THAT-WONT-RUN-ON-SERVER ::= [
"import ble",
"import esp32",
"import system.containers",
+ "import net.cellular",
]
main args -> none:
diff --git a/tutorial_code/cellular/cellular-user.toit b/tutorial_code/cellular/cellular-user.toit
new file mode 100644
index 00000000..e834551f
--- /dev/null
+++ b/tutorial_code/cellular/cellular-user.toit
@@ -0,0 +1,14 @@
+import net
+import net.cellular
+
+main:
+ network := cellular.open --name="walter" {:}
+
+ try:
+ do-network-things network
+ finally:
+ network.close
+
+
+do-network-things network/net.Client:
+ // Use the network.
diff --git a/tutorial_code/cellular/cellular.toit b/tutorial_code/cellular/cellular.toit
new file mode 100644
index 00000000..10f3afb6
--- /dev/null
+++ b/tutorial_code/cellular/cellular.toit
@@ -0,0 +1,28 @@
+import net.cellular
+import cellular.modules.sequans.monarch
+
+RX ::= 14
+TX ::= 48
+RTS ::= 21
+CTS ::= 47
+RESET ::= 45
+POWER ::= 46
+BAUD ::= 115200
+
+class WalterCellularProvider extends monarch.MonarchService:
+ connect client/int config/Map? -> List:
+ if not config or config.is-empty:
+ config = {
+ cellular.CONFIG-UART-RX: RX,
+ cellular.CONFIG-UART-TX: TX,
+ cellular.CONFIG-UART-CTS: CTS,
+ cellular.CONFIG-UART-RTS: RTS,
+ cellular.CONFIG-RESET: [RESET, cellular.CONFIG-ACTIVE-LOW],
+ cellular.CONFIG-POWER: POWER,
+ cellular.CONFIG-UART-BAUD-RATE: BAUD,
+ }
+ return super client config
+
+main:
+ provider := WalterCellularProvider
+ provider.install
diff --git a/tutorial_code/cellular/package.lock b/tutorial_code/cellular/package.lock
new file mode 100644
index 00000000..301c9f24
--- /dev/null
+++ b/tutorial_code/cellular/package.lock
@@ -0,0 +1,21 @@
+sdk: ^2.0.0-alpha.108
+prefixes:
+ cellular: cellular
+ certificate_roots: toit-cert-roots
+ http: pkg-http
+packages:
+ cellular:
+ url: github.com/toitware/cellular
+ name: cellular
+ version: 2.1.10
+ hash: a2b641e2da596ac1fd58b5fd5ce5e26d5e501c35
+ pkg-http:
+ url: github.com/toitlang/pkg-http
+ name: http
+ version: 2.3.4
+ hash: 39fe52083b4c745cc37420649a48277b45728fd2
+ toit-cert-roots:
+ url: github.com/toitware/toit-cert-roots
+ name: certificate_roots
+ version: 1.6.1
+ hash: 55d3be82ed53d8d332338b2de931865cf69fe48b
diff --git a/tutorial_code/cellular/package.yaml b/tutorial_code/cellular/package.yaml
new file mode 100644
index 00000000..c0cca4a5
--- /dev/null
+++ b/tutorial_code/cellular/package.yaml
@@ -0,0 +1,10 @@
+dependencies:
+ cellular:
+ url: github.com/toitware/cellular
+ version: ^2.1.10
+ certificate_roots:
+ url: github.com/toitware/toit-cert-roots
+ version: ^1.6.1
+ http:
+ url: github.com/toitlang/pkg-http
+ version: ^2.3.4
diff --git a/tutorial_code/cellular/walter.toit b/tutorial_code/cellular/walter.toit
new file mode 100644
index 00000000..62437e62
--- /dev/null
+++ b/tutorial_code/cellular/walter.toit
@@ -0,0 +1,43 @@
+import cellular.modules.sequans.monarch
+import http
+import encoding.json
+import net
+import net.cellular
+import certificate-roots
+
+RX ::= 14
+TX ::= 48
+RTS ::= 21
+CTS ::= 47
+RESET ::= 45
+POWER ::= 46
+BAUD ::= 115200
+
+main:
+ // Start the monarch driver/provider.
+ task --background::
+ monarch.main
+
+ // Establish the connection to the network.
+ network := cellular.open --name="gm02sp" {
+ cellular.CONFIG-UART-RX: RX,
+ cellular.CONFIG-UART-TX: TX,
+ cellular.CONFIG-UART-CTS: CTS,
+ cellular.CONFIG-UART-RTS: RTS,
+ cellular.CONFIG-RESET: [RESET, cellular.CONFIG-ACTIVE-LOW],
+ cellular.CONFIG-POWER: POWER,
+ cellular.CONFIG-UART-BAUD-RATE: BAUD,
+ }
+
+ try:
+ do-network-things network
+ finally:
+ network.close
+
+do-network-things network/net.Client:
+ client := http.Client.tls network
+ --root-certificates=[certificate-roots.GTS-ROOT-R1]
+ request := client.get --uri="https://official-joke-api.appspot.com/random_joke"
+ decoded := json.decode-stream request.body
+ print decoded["setup"]
+ print decoded["punchline"]