---
title: Using Mesh Presence
slug: v4-7/sync/using-mesh-presence
docTags: 
createdAt: 2024-03-21T18:19:48.836Z
---

This article provides a high-level overview of *peer-presence data* within the mesh network. Peer-presence data, or *presence* for short, refers to the information Ditto uses within the mesh network to track peer connectivity within physical proximity.&#x20;

To get realtime updates about changes to presence data, use the Presence API. This article includes instructions on how to implement Ditto's Presence APIs to enable the following end-user functionality for network monitoring and management within your app:

- Setting and updating peer-specific information, such as name, role, and location.
- Viewing information about other peers currently connected in the mesh.

# Accessing Presence APIs

To access API methods for mesh presence functionality, call the the `presence` namespace on the root `Ditto` object:

:::CodeblockTabs
```swift
ditto.presence
```

```kotlin
ditto.presence
```

```javascript
ditto.presence
```

```java
ditto.getPresence();
```

```csharp
Ditto.Presence
```

```cpp
ditto.get_presence()
```

```rust
ditto.presence()
```

Dart (beta)

```dart
// Coming Soon
```
:::

# Presence Graph

Once discovered in the mesh, peers automatically establish a *presence graph* by advertising their device presence within the mesh and forming network connections with other connected peers.&#x20;

The presence graph is a data structure representing the current state of the mesh from a specific peer's point of view.&#x20;

You can integrate the presence graph into your app to enable end-user functionality like network monitoring, management, and transport optimization. For example, once implemented, end users can input personal information, such as their name, and inspect remote peers connected within the mesh. For more information, see [DittoSwiftTools](https://github.com/getditto/DittoSwiftTools) on GitHub.

## Accessing Presence Graphs

To view your current presence graph:

:::CodeblockTabs
```swift
let presenceGraph = ditto.presence.graph
```

```kotlin
val presenceGraph = ditto.presence.graph
```

```javascript
const presenceGraph = ditto.presence.graph
```

```java
DittoPresenceGraph graph = ditto.getPresence().getGraph();
```

```csharp
var PresenceGraph = Ditto.Presence.Graph
```

```cpp
auto presenceGraph = ditto.get_presence().graph()
```

```rust
let presenceGraph = ditto.presence().graph()
```

Dart (beta)

```dart
// Coming Soon
```
:::

Once invoked, Ditto returns the following object, allowing you to perform actions like displaying the status of connected peers and managing network resources:

:::CodeblockTabs
Presence Graph Response

```json
{
  localPeer: Peer;
  remotePeers: Peer[];
}
```
:::

The `localPeer` is the metadata set by the end user within your app. The `remotePeers` property provides an `array` of the other client devices connected to the mesh. (See [End-User Defined Metadata](./#end-user-defined-metadata))

## Observing Presence Graph Modifications&#x20;

To monitor and handle changes observed to the presence graph, call the change handler with the updated graph object as follows:

:::hint{type="warning"}
Make sure the observer response object remains in memory during runtime; otherwise, Ditto removes it during the periodic garbage collection process running in the background, resulting in the change handler no longer being triggered.
:::

:::CodeblockTabs
```swift
let presenceObserver = ditto.presence.observe { presenceGraph in
    // observe changes to the presence graph
}
```

```kotlin
val presenceObserver = ditto.presence.observe { graph -> 
    // observe changes to the presence graph
}
```

```javascript
const presenceObserver = ditto.presence.observe((presenceGraph) => {
    // observe changes to the presence graph
})
```

```java
DittoPresenceObserver presenceObserver = ditto.getPresence().observe(graph -> {  
    // observe changes to the presence graph
});
```

```csharp
var presenceObserver = Ditto.Presence.Observe((DittoPresenceGraph graph) =>
{
    // Observe changes to the presence graph
});
```

```cpp
auto presenceObserver = ditto.get_presence().observe([&](PresenceGraph graph) {
    // observe changes to the presence graph
});
```

```rust
let presenceObserver = ditto.presence().observe(move |_graph| {
    // observe changes to the presence graph
});
```

Dart (beta)

```dart
// Coming Soon
```
:::

# Peer Key Identifier

Once discovered in the mesh, each peer device running Ditto is automatically assigned a *peer key*.

## Reading Peer Keys

View your local device's peer key or the peer key identifying a specific remote device:

- To retrieve the peer key for the current peer:

:::CodeblockTabs
```swift
ditto.presence.graph.localPeer.peerKeyString
```

```kotlin
ditto.presence.graph.localPeer.peerKeyString
```

```javascript
ditto.presence.graph.localPeer.peerKeyString
```

```java
ditto.getPresence().getGraph().localPeer.peerKeyString
```

```csharp
Ditto.Presence.Graph.LocalPeer.PeerKeyString
```

```cpp
ditto.get_presence().graph().local_peer.peer_key_string
```

```rust
ditto.presence().graph().local_peer.peer_key_string
```

Dart (beta)

```dart
// Coming Soon
```
:::

- To retrieve the peer key for a remote peer:

:::CodeblockTabs
```swift
let remotePeers = presenceGraph.remotePeers
let firstPeer = remotePeers.first!

let peerkeyString = firstPeer.peerKeyString
```

```kotlin
val remotePeers = ditto.presence.graph.remotePeers
val firstPeer = remotePeers.first()

val peerKeyString = firstPeer.peerKeyString
```

```javascript
const remotePeers = ditto.presence.graph.remotePeers
const firstPeer = remotePeers[0]

const peerkeyString = firstPeer.peerKeyString
```

```java
List<DittoPeer> remotePeers = ditto.getPresence().getGraph().remotePeers
DittoPeer firstPeer = remotePeers.get(0)

String peerKeyString = firstPeer.peerKeyString
```

```csharp
DittoPeer remotePeers = ditto.presence.graph.remotePeers
const firstPeer = remotePeers[0]

const peerkeyString = firstPeer.peerKeyString
```

```cpp
auto remotePeers = ditto.get_presence().graph().remote_peers;
auto firstPeer = remotePeers[0];

auto peerkeyString = firstPeer.peer_key_string;
```

```rust
let remote_peers = ditto.presence().graph().remote_peers;
let first_peer = &remote_peers[0];

let peer_key_string = &first_peer.peer_key_string;
```

Dart (beta)

```dart
// Coming Soon
```
:::

# End-User Defined Metadata

Using the peer-metadata property, you can provide each peer connected within the mesh the ability to set and view information about themselves or read information defined by other peers within the mesh.&#x20;

The following table provides an overview of key considerations to know before setting peer metadata, as well as Ditto's recommended best practices to ensure optimal mesh performance and avoid potential issues:

| **Consideration**                                                                                                                                                                                                                     | **Best Practice**                                                                                                                                                                                                                                            |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Peer metadata syncs across the mesh with each new connection. Therefore, sharing large data over low-bandwidth transports, such as Bluetooth Low Energy (LE), and low-quality connections may slow or disrupt the connection process. | Keep the size of peer metadata to a minimum, especially when syncing over Bluetooth LE or similar low-bandwidth transports. This is because peer metadata exceeding 128 KB, the maximum limit, results in the operation failing and Ditto throwing an error. |
| Peer metadata is visible to all peers connected in the mesh.                                                                                                                                                                          | Include only non-sensitive information in peer metadata.                                                                                                                                                                                                     |

## Setting Local Peer Metadata

To implement functionality providing end users the ability to define metadata, call the `setPeerMetadata` API method as follows:

:::CodeblockTabs
```swift
// Setting via Object
try ditto.presence.setPeerMetadata(["location": "inside"])

// Setting via JSON String
let jsonData = "{location:\"inside\"}".data(using: .utf8)!
try ditto.presence.setPeerMetadataJSONData(jsonData)
```

```kotlin
// Setting via Object
ditto.presence.peerMetadata = mapOf("number" to 1)

// Setting via JSON String
ditto.presence.peerMetadataJsonString =
    """  
    {"location":"inside"}
    """.trimIndent()
```

```javascript
// Setting via Object
await ditto.presence.setPeerMetadata({ location: "inside" })

// Setting via JSON String
await ditto.presence.setPeerMetadataJSONString("{location:\"inside\"}")
```

```java
// Setting via Object
ditto.getPresence().setPeerMetadata(  
    Collections.singletonMap("number", 1)  
);

// Setting via JSON String
ditto.getPresence().setPeerMetadataJsonString("{\"location\":\"inside\"}");
```

```csharp
Ditto.Presence.SetPeerMetadata(new Dictionary<string, object>()  { { "location", "inside" } });
```

```cpp
nlohmann::json metadata = {
    {"location", "inside"}
};

ditto.get_presence().set_peer_metadata(metadata);
```

```rust
let metadata = json!({
    "location": "inside",
});
ditto.presence().set_peer_metadata(&metadata)?;
```

Dart (beta)

```dart
// Coming Soon
```
:::

## Reading Local Peer Metadata

Once set, inspect the metadata:

:::CodeblockTabs
```swift
// Reading from the presence namespace
ditto.presence.peerMetadata

// Reading from the presence graph
ditto.presence.graph.localPeer.peerMetadata
```

```kotlin
// Reading from the presence namespace
ditto.presence.peerMetadata

// Reading from the presence graph
ditto.presence.graph.localPeer.peerMetadata
```

```javascript
// Reading from the presence namespace
ditto.presence.peerMetadata

// Reading from the presence graph
ditto.presence.graph.localPeer.peerMetadata
```

```java
// Reading from the presence namespace
Map<String, Object> metadata = ditto.getPresence().getPeerMetadata();

// Reading from the presence graph
Map<String, Object> metadata2 = ditto.getPresence().getGraph().localPeer.peerMetadata;
```

```csharp
// Reading from the presence namespace
Ditto.Presence.PeerMetadata;

// Reading from the presence graph
Ditto.Presence.Graph.LocalPeer.PeerMetadata;
```

```cpp
// Reading from the presence namespace
ditto.get_presence().peer_metadata()

// Reading from the presence graph
ditto.get_presence().graph().local_peer.peer_metadata
```

```rust
// Reading from the presence namespace
ditto.presence().peer_metadata()

// Reading from the presence graph
ditto.presence().graph().local_peer.peer_metadata
```

Dart (beta)

```dart
// Coming Soon
```
:::

## Reading Remote Peer Metadata

To inspect the metadata set by all other peers in the mesh:

:::CodeblockTabs
```swift
let remotePeers = ditto.presence.graph.remotePeers
let firstPeer = remotePeers.first!

let peerMetadata = firstPeer.peerMetadata
```

```kotlin
val remotePeers = ditto.presence.graph.remotePeers
val firstPeer = remotePeers.first()

val peerMetadata = firstPeer.peerMetadata
```

```javascript
const remotePeers = ditto.presence.graph.remotePeers
const firstPeer = remotePeers[0]

const peerMetadata = firstPeer.peerMetadata
```

```java
List<DittoPeer> remotePeers = ditto.getPresence().getGraph().remotePeers;  
DittoPeer firstPeer = remotePeers.get(0);

Map<String, Object> metadata = firstPeer.peerMetadata;
```

```csharp
var RemotePeers = Ditto.Presence.Graph.RemotePeers.PeerMetadata;
var FirstPeer = RemotePeers[0];

var PeerMetadata = FirstPeer.PeerMetadata;
```

```cpp
auto remotePeers = ditto.get_presence().graph().remote_peers;
auto firstPeer = remotePeers[0];

auto peerMetadata = firstPeer.peer_metadata();
```

```rust
let remote_peers = ditto.presence().graph().remote_peers;
let first_peer = &remote_peers[0];

let peer_metadata = &first_peer.peer_metadata;
```

Dart (beta)

```dart
// Coming Soon
```
:::

