diff --git a/website/docs/zephyr-training/05_golioth/kconfig_and_client.md b/website/docs/zephyr-training/05_golioth/kconfig_and_client.md
index 5b89bf8..4be2f43 100644
--- a/website/docs/zephyr-training/05_golioth/kconfig_and_client.md
+++ b/website/docs/zephyr-training/05_golioth/kconfig_and_client.md
@@ -8,10 +8,10 @@ description:
## Learning objectives
-Now that the Golioth Zephyr SDK has been added to your Zephyr installation we
+Now that the Golioth Firmware SDK has been added to your Zephyr installation we
are ready to start using it. As with all Zephyr libraries, we need to first
-enable Golioth using some Kconfig symbols. Then we create the Golioth System
-Client to handle all things Golioth.
+enable Golioth using some Kconfig symbols. Then we create the Golioth Client to
+handle all things Golioth.
* **Desired outcome(s)**
1. Understand how to enable Kconfig symbols required by the Golioth SDK
@@ -28,41 +28,79 @@ example.
## Kconfig symbols required by Golioth
-There are two Kconfig symbols that are always required to use the Golioth Zephyr
-SDK:
+There is one Kconfig symbol required to use the Golioth Zephyr SDK:
```kconfig
-CONFIG_GOLIOTH=y
-CONFIG_GOLIOTH_SYSTEM_CLIENT=y
+CONFIG_GOLIOTH_FIRMWARE_SDK=y
```
-These will immediately allow you to connect to Golioth to send and receive data
-on LightDB Stream and LightDB state. The logging and RPC services are similarly
-easy to enable:
+These will immediately allow you to connect to Golioth, however each Golioth
+service must be individually enabled. This helps conserve device resources by
+only including what you need in the firmware build. Here is an example of the
+Kconfig symbols used for our services:
```
-# Enable remote logging
+# Enable OTA firmware update
+CONFIG_GOLIOTH_FW_UPDATE=y
+
+# Enable stateful data
+CONFIG_GOLIOTH_LIGHTDB_STATE=y
+
+# Enable sending log messages to the Golioth cloud
CONFIG_LOG_BACKEND_GOLIOTH=y
# Enable remote procedure call
CONFIG_GOLIOTH_RPC=y
+
+# Enable fleet-wide device settings
+CONFIG_GOLIOTH_SETTINGS=y
+
+# Enable time-series data
+CONFIG_GOLIOTH_STREAM=y
```
-More setup is required for the settings service and for OTA firmware updates.
Generally speaking, see [the Golioth Zephyr
samples](https://github.com/golioth/golioth-zephyr-sdk/tree/main/samples) for
information on enabling services.
-:::note
-
-Golioth Kconfig symbols are already enabled in the `prj.conf` file of the
-`05_golioth` application we're working with in this module. If you're curious,
-you may use `menuconfig` and navigate to `modules`→`golioth` to see the
-full configuration for Golioth.
-
-![Golioth menuconfig options](./assets/golioth_menuconfig_options.jpg)
+
+ Explain the Golioth Kconfig symbols present in the 05_golioth sample code
+
+Some Golioth Kconfig symbols are already enabled [in the `prj.conf` file of the
+`05_golioth`
+application](https://github.com/golioth/zephyr-training/blob/main/05_golioth/prj.conf)
+we're working with in this module.
+
+* We use the [Golioth common
+ library](https://github.com/golioth/golioth-firmware-sdk/tree/main/examples/zephyr/common)
+ for credential and connection management
+
+ ```
+ CONFIG_GOLIOTH_SAMPLE_COMMON=y
+ ```
+
+* These symbols enable [Golioth runtime
+ settings](https://github.com/golioth/golioth-firmware-sdk/blob/main/examples/zephyr/hello/README.md#psk-based-auth---runtime)
+ so that WiFi and Golioth credentials can be stored in the settings partition
+ from the shell
+
+ ```
+ CONFIG_GOLIOTH_SETTINGS=y
+ CONFIG_SETTINGS=y
+ CONFIG_SETTINGS_RUNTIME=y
+ CONFIG_GOLIOTH_SAMPLE_HARDCODED_CREDENTIALS=n
+ CONFIG_GOLIOTH_SAMPLE_PSK_SETTINGS=y
+ CONFIG_GOLIOTH_SAMPLE_SETTINGS_AUTOLOAD=y
+ CONFIG_GOLIOTH_SAMPLE_SETTINGS_SHELL=y
+
+ CONFIG_FLASH=y
+ CONFIG_FLASH_MAP=y
+ CONFIG_NVS=y
+
+ CONFIG_SHELL=y
+ ```
-:::
+
## Exercise: Create a Golioth Client in main.c
@@ -74,22 +112,28 @@ API calls in our C code.
Add the following code to the `05_golioth/src/main.c` file:
```c
-#include
-
-static struct golioth_client *client = GOLIOTH_SYSTEM_CLIENT_GET();
+#include
+static struct golioth_client *client;
static K_SEM_DEFINE(connected, 0, 1);
-static void golioth_on_connect(struct golioth_client *client)
+static void on_client_event(struct golioth_client *client,
+ enum golioth_client_event event,
+ void *arg)
{
- k_sem_give(&connected);
+ bool is_connected = (event == GOLIOTH_CLIENT_EVENT_CONNECTED);
+
+ if (is_connected) {
+ k_sem_give(&connected);
+ }
+ LOG_INF("Golioth client %s", is_connected ? "connected" : "disconnected");
}
```
Here's what's happening in this block:
1. Include the Golioth System Client at the top of the file
-2. Create a pointer to a `golioth_client` singleton
+2. Create a pointer to a `golioth_client` instance
3. Create a semaphore to block until a connection with Golioth is established
4. Create a callback that will be used when we connect to Golioth
* This callback will unblock the semaphore, allowing program execution to
@@ -101,28 +145,88 @@ Finally, add this code in your `main()` function, after the network connection
function calls, but before the loop:
```c
- client->on_connect = golioth_on_connect;
- golioth_system_client_start();
+/* Get golioth_client_config filled with PSK-ID/PSK credentials
+ * using Golioth common Library */
+const struct golioth_client_config *client_config = golioth_sample_credentials_get();
- k_sem_take(&connected, K_FOREVER);
+/* Use golioth_client_config to create the Golioth client */
+client = golioth_client_create(client_config);
+
+/* Register a callback to run when we connect to Golioth */
+golioth_client_register_event_callback(client, on_client_event, NULL);
+
+/* Block program flow until connection is ready */
+k_sem_take(&connected, K_FOREVER);
```
This block serves the following purpose:
-1. Register the callback to be used when the Golioth System Client connects
-2. Start the Golioth System Client
-3. Block program execution until the connection is established
+1. Get the stored credentials
+2. Create the Golioth client
+3. Register a callback so we can do things when first connected to Golioth
+4. Block program execution until the connection is established
:::tip
-The Golioth System Client runs on its own thread. Since we cannot send or
-receive anything from Golioth until a connection is established it makes sense
-for simple demo code to block program flow until that point. In production, you
-may want to adopt a different approach that allows other parts of your
-application to run while waiting for a connection.
+The Golioth client runs on its own thread. Since we cannot send or receive
+anything from Golioth until a connection is established, it makes sense for
+simple demo code to block program flow until that point. In production, you may
+want to adopt a different approach that allows other parts of your application
+to run while waiting for a connection.
:::
+### More information on credentials
+
+This example uses a helper function to get the runtime credentials and use them
+when creating the Golioth client. But the Golioth client is designed to make
+this step configurable. You may be using credentials stored in a secure
+keystore, or loaded in from a storage location of your choosing. Here are a few
+examples of different golioth_client_config structs:
+
+```c
+/* Config for Certificate authentication */
+struct golioth_client_config client_config = {
+ .credentials =
+ {
+ .auth_type = GOLIOTH_TLS_AUTH_TYPE_PKI,
+ .pki =
+ {
+ .ca_cert = tls_ca_crt,
+ .ca_cert_len = sizeof(tls_ca_crt),
+ .public_cert = tls_client_crt,
+ .public_cert_len = tls_client_crt_len,
+ .private_key = tls_client_key,
+ .private_key_len = tls_client_key_len,
+ },
+ },
+};
+
+/* Config for PSK authentication */
+struct golioth_client_config client_config = {
+ .credentials =
+ {
+ .auth_type = GOLIOTH_TLS_AUTH_TYPE_PSK,
+ .psk =
+ {
+ .psk_id = client_psk_id,
+ .psk_id_len = client_psk_id_len,
+ .psk = client_psk,
+ .psk_len = client_psk_len,
+ },
+ },
+};
+
+/* Config for credential tag authentication */
+struct golioth_client_config client_config = {
+ .credentials =
+ {
+ .auth_type = GOLIOTH_TLS_AUTH_TYPE_TAG,
+ .tag = YOUR_CREDENTIALS_TAG,
+ },
+};
+```
+
## Expected results
You have added Golioth to your application. The code will build and attempt to
@@ -135,29 +239,39 @@ LightDB Steam.
Here is an excerpt from `main.c` that includes the added code from this section:
```c
-#include /* already included in earlier */
-
-static struct golioth_client *client = GOLIOTH_SYSTEM_CLIENT_GET();
+/* There are existing file contents above this line that aren't shown */
+/* - additions you should have made are highlighted below */
+// highlight-start
+#include
+static struct golioth_client *client;
static K_SEM_DEFINE(connected, 0, 1);
-static void golioth_on_connect(struct golioth_client *client)
+static void on_client_event(struct golioth_client *client,
+ enum golioth_client_event event,
+ void *arg)
{
- k_sem_give(&connected);
+ bool is_connected = (event == GOLIOTH_CLIENT_EVENT_CONNECTED);
+
+ if (is_connected) {
+ k_sem_give(&connected);
+ }
+ LOG_INF("Golioth client %s", is_connected ? "connected" : "disconnected");
}
+// highlight-end
/* Main function */
-void main(void)
+int main(void)
{
int ret;
if (!device_is_ready(led1.port)) {
- return;
+ return -EIO;
}
ret = gpio_pin_configure_dt(&led1, GPIO_OUTPUT_ACTIVE);
if (ret < 0) {
- return;
+ return -EIO;
}
/* Start timer-based LED blinker */
@@ -167,15 +281,17 @@ void main(void)
#ifdef CONFIG_BOARD_NRF7002DK_NRF5340_CPUAPP
wifi_connect();
#else
- if (IS_ENABLED(CONFIG_GOLIOTH_SAMPLES_COMMON)) {
+ if (IS_ENABLED(CONFIG_GOLIOTH_SAMPLE_COMMON)) {
net_connect();
}
#endif
- client->on_connect = golioth_on_connect;
- golioth_system_client_start();
-
+ // highlight-start
+ const struct golioth_client_config *client_config = golioth_sample_credentials_get();
+ client = golioth_client_create(client_config);
+ golioth_client_register_event_callback(client, on_client_event, NULL);
k_sem_take(&connected, K_FOREVER);
+ // highlight-end
int counter = 0;