# Development

Build WASM modules to transform uplink and downlink device data.

When Orbit processes data, it will call the `uplink()` or `downlink()` function of a WASM module whenever a device sends data to the Unified Endpoint, or a server or cloud service sends a response to the device, respectively.

These functions do not take any arguments. Instead, use the **getInput** (or equivalent) functions provided by each SDK to read the incoming value, and the **setOutput** (or equivalent) functions to define the transformed outgoing value.

These functions should return an integer (_i32_) value indicating whether the function succeeded (returning `0` or positive value) or failed (returning a negative value).

When you develop a WASM module, keep in mind:

- Orbit will use the version of the WASM module specified in the group configuration.
- Orbit will return an error if it performs an unsupported operation, or if the WASM module terminates unexpectedly.
- WASM module execution is independent. The result of a single `uplink()` or `downlink()` call cannot be stored or referenced later. Similarly, a WASM module cannot execute another WASM module.

Note that WebAssembly System Interface (WASI) is not supported, so system calls such as file system operations or network access cannot be implemented in a Soralet module. The external interface for reading input data and setting output data is defined in the Orbit SDK. Refer to the [SDK Reference](https://docs.soracom.io/en/services/orbit/reference) for details.

If Binary Parser is also enabled, Binary Parser will execute first, and the results will be passed into the WASM module as the input data.

## Development Notes

- After exiting VS Code, make sure to click the **Reopen in Container** prompt when you open your Orbit development environment again in order to load the development container.
- If you edit your `.devcontainer/devcontainer.json` configuration, you will be prompted to rebuild your Docker image. Click **Rebuild** in order to rebuild the development container with your updated configuration.

## AssemblyScript

The Orbit AssemblyScript SDK includes a template script located at `assembly/index.ts`. You can edit this file to implement your data processing code.

Your code should export an `uplink()` function, a `downlink()` function, or both.

```ts
// For processing uplink (Device to Soracom)
export function uplink(): i32 {
  /* code  */
}

// For processing downlink (Soracom to Device)
export function downlink(): i32 {
  /* code */
}
```

When you have finished editing `assembly/index.ts`, compile it into a WASM module using one of the following methods in VS Code:

- Open the **NPM Scripts** view, select the `build` script, and click **Run**
- Open the integrated terminal and run `npm run build`
- Open the command palette (`⌘-⇧-P` or `Ctrl-Shift-P`) and run the `Run Build Task` command
- Run the `Run Build Task` command using the `⌘-⇧-B` or `Ctrl-Shift-B` shortcut

The compiled WASM module will be saved to `build/soralet.wasm`.

## Rust

The Orbit Rust SDK includes a template script located at `src/lib.rs`. You can edit this file to implement your data processing code.

Your code should define a public `uplink()` function, a public `downlink()` function, or both. Ensure that you include the `#[no_mangle]` attribute in order to prevent symbol names from being mangled during compile, so that Orbit can correctly reference the functions.

```rust
// For processing uplink (Device to Soracom)
#[no_mangle]
pub fn uplink() -> i32 {
  /* code */
}

// For processing downlink (Soracom to Device)
#[no_mangle]
pub fn downlink() -> i32 {
  /* code */
}
```

When you have finished editing `src/lib.rs`, compile it into a WASM module using one of the following methods in VS Code:

- Open the integrated terminal and run `cargo build`
- Open the command palette (`⌘-⇧-P` or `Ctrl-Shift-P`) and run the `Run Build Task` command
- Run the `Run Build Task` command using the `⌘-⇧-B` or `Ctrl-Shift-B` shortcut

The compiled WASM module will be saved to `target/wasm32-unknown-unknown/debug/soralet.wasm`.

## C/C++

The Orbit C/C++ SDK includes a template source code file located at `src/main.cpp`. You can edit this file to implement your data processing code.

Your code should export either an `uplink()` function, a `downlink()` function, or both. Ensure that you include the `EMSCRIPTEN_KEEPALIVE` macro in order to supress compiler optimization so that Orbit can correctly reference the functions.

If using C++, ensure that you enclose these functions in `extern "C" { ... }` in order to supress mangled function names.

```cpp
// For processing uplink (UE to SORACOM)
EMSCRIPTEN_KEEPALIVE
int32_t uplink()
{
    /* code */
    return 0;
}

// For processing downlink (SORACOM to UE)
EMSCRIPTEN_KEEPALIVE
int32_t downlink()
{
    /* code */
    return 0;
}
```

When you have finished editing `src/main.cpp`, compile it into a WASM module using one of the following methods in VS Code:

- Open the integrated terminal and run `make build`
- Open the command palette (`⌘-⇧-P` or `Ctrl-Shift-P`) and run the `Run Build Task` command
- Run the `Run Build Task` command using the `⌘-⇧-B` or `Ctrl-Shift-B` shortcut

The compiled WASM module will be saved to `build/soralet.wasm`.

> [!NOTE]
>
> When building, you may see warnings that certain functions (beginning with an `orbit_` prefix, such as `orbit_log` and `orbit_get_input_buffer`) are undefined. These functions are provided directly by Orbit during runtime, so you can safely ignore these warnings.

## TinyGo

The Orbit TinyGo SDK includes a template source code file located at `src/main.go`. You can edit this file to implement your data processing code.

Your code should export either an `uplink()` function, a `downlink()` function, or both. Ensure that you include the `//export uplink` or `//export downlink` comment so that Orbit can correctly reference the functions.

> [!NOTE]
>
> Note that there are no whitespace characters after `//` and after `uplink`/`downlink`.

```go
import sdk github.com/soracom/orbit-sdk-tinygo

// For processing uplink (UE to SORACOM)
//export uplink
func uplink() sdk.ErrorCode {
  sdk.Log("hello world, uplink")
  return 0
}

// For processing downlink (SORACOM to UE)
//export downlink
func downlink() sdk.ErrorCode {
  sdk.Log("hello world, downlink")
  return 0
}
```

When you have finished editing `src/main.go`, compile it into a WASM module using one of the following methods in VS Code:

- Open the integrated terminal and run `make build`
- Open the command palette (`⌘-⇧-P` or `Ctrl-Shift-P`) and run the `Run Build Task` command
- Run the `Run Build Task` command using the `⌘-⇧-B` or `Ctrl-Shift-B` shortcut

The compiled WASM module will be saved to `build/soralet.wasm`.
