swim.ai and Pelion Device Management [Pelion Device Management](https://www.pelion.com/iot-device-management/) provides an extensive API for IoT developers to be able to plug in and provide their value-added services on top. In this blog post, we are going to explore an example of such as service we developed in collaboration with the swim.ai team, that allows us to create '_digital twins_' of the devices connected to Pelion IoT platform. Those twins serve as a digital representation of the devices, encapsulating the resources they support and allowing us to programmatically access them using the client interface provided by swim.ai. Those twins can be made to run in the cloud or at the edge allowing us to create interesting integration scenarios tailored to specific use cases. > The blog assumes you have basic knowledge of Pelion Device Management service and how [Device Resources](https://www.pelion.com/docs/device-management/current/resources/index.html) and [Event Notification Channels](https://www.pelion.com/docs/device-management/current/integrate-web-app/event-notification.html) operate. If not, visit our respective documentation pages for more information and our previous [blog post](https://blog.pelion.com/post/lwm2m-and-pelion-iot-platform) as a general introduction to device resources. ## About Swim [SwimOS](https://www.swim.ai/) is a complete, self-contained open-source software core for building and running continuous intelligence applications. SwimOS implements a distributed microkernel, called the Swim Kernel, that is persistent without a database, reactive without a message broker, autonomous without a job manager. SwimOS can power a stand-alone application or integrate with existing applications to provide stateful, real-time compute on-premises, in the cloud or at the edge. At its core, SwimOS provides what are called [Web Agents](https://www.swimos.org/tutorials/web-agents/). Similar to digital twins, Swim Web Agents are stateful, autonomous, digital agents that can aggregate, transform, analyze and act upon dynamic and static data in real-time. But Swim Web Agents can also take action on behalf of their real-world entities as well as communicate with other Web Agents, all in real-time using standard URIs. They enable general-purpose compute, allowing any kind of business logic, not just a limited set of analytical functions, to be processed with streaming and contextual data. Swim Web Agents are also able to communicate with 3rd party APIs and services such as [Pelion Device Management Connect API](https://www.pelion.com/docs/device-management/current/service-api-references/index.html) to create stateful Web Agents for devices managed by Pelion. In this example we will demonstrate how to use stateful Web Agents to create digital twins of devices managed by Pelion Device Management and read sensor data from those devices via the [Pelion Connect API](https://www.pelion.com/docs/device-management/current/service-api-references/service-api-documentation.html). This demo also shows how to act upon that real-time data inside a Web Agent by triggering ‘alerts’ for sensor values which go outside of a threshold, which is also defined inside the Agent. ![architecture](https://i.ibb.co/tD3RPNx/pelion-dataflow-diagram.png) ## Application Structure Application has three main WebAgent types. These three types are the [AggregationService](https://github.com/swimos/plant-monitor/blob/pelion/java/src/main/java/plantmonitor/agents/AggregationService.java), [PlantState](https://github.com/swimos/plant-monitor/blob/pelion/java/src/main/java/plantmonitor/agents/PlantState.java), and [SensorState](https://github.com/swimos/plant-monitor/blob/pelion/java/src/main/java/plantmonitor/agents/SensorState.java). Each of these agents can communicate with each other to share data and create an application structure. **AggregationService** - The Aggregation Service Web Agent keeps track of things that are global to the application such as the list of all plants, alerts and application config. The application will only have a single Aggregation Web Agent and the agent is started by the [Application Plane](https://github.com/swimos/plant-monitor/blob/pelion/java/src/main/java/plantmonitor/ApplicationPlane.java) on app startup. **PlantState** - The PlantState Web Agent represents the digital twin of the device being managed by Pelion. Each device has a collection of sensors attached to it and each of those sensors map to a resource on the device. In this example, the [bridge](https://github.com/swimos/plant-monitor/blob/pelion/node/main.js) which we'll discuss later, is using a [config file](https://github.com/swimos/plant-monitor/blob/pelion/config/localhost.json) to route data coming from the Pelion Connect API back to the correct Sensor Web Agent for this plant. **SensorState** - The Sensor State Web Agent represents the state of a single resource on a device, being managed by the Pelion Device Management. A Sensor WebAgent is created by the bridge during device registration and automatically registers itself with its parent Plant Web Agent based on the plantID sent as part of sensor info. ## Pelion Connect API Bridge In this example, we use NodeJS to bridge data between the Pelion Connect API and the WebAgents inside our Swim Application. Since the [bridge](https://github.com/swimos/plant-monitor/blob/pelion/node/main.js) uses basic HTTP requests and the Swim Client, for simplicity we are using JavaScript but the bridge could also be written in Java, Python, or Rust. Both the bridge and the main Swim application also share the same [configuration](https://github.com/swimos/plant-monitor/blob/pelion/config/localhost.json) file to make things easier. On startup, the bridge will send http requests to clear any existing [Pelion notification subscriptions](https://www.pelion.com/docs/device-management/current/resources/resource-change-webapp.html) for your API Key, made by previous invocations of the application. It then proceeds to establish a [websocket notification channel](https://www.pelion.com/docs/device-management/current/integrate-web-app/event-notification.html) with Pelion Connect API to start receiving all changes happening from the connected devices and continuously update the internal state of the WebAgents. Once the websocket channel is opened, a new http request is sent to retrieve all devices being managed by your API key. For each device in the list, we check the device status and if it is marked as `registered`, then the bridge will send a command to Swim to create a new Plant WebAgent using the device information returned from the API. The Plant WebAgent will now act as the digital twin of the device registered to Pelion. The bridge will use the "endpoints" data from the configuration file to create [notification subscriptions]((https://www.pelion.com/docs/device-management/current/resources/resource-change-webapp.html)) and the respective Sensor WebAgents for each resource endpoint. After the bridge finishes creating subscriptions, subsequent notifications for sensor value changes will come across the websocket channel. It uses the configuration data along with the device endpoint data to route the notifications to the correct sensor for the correct plant. This mapping is based on the device and resource IDs provided by Pelion Device Management. All resource data sent to and from the Connect API is Base64 encoded. The bridge handles both decoding and encoding message so that our Swim Application is always dealing with unencoded data. To allow for communication back to the Connect API from the application UI, the bridge also passes along "AsyncIDs" for resources which support them. Those IDs are stored in the Sensor WebAgent the ID is associated with. By doing this, we can set up command lanes in those Web Agents which allow the UI to call back to resources on the parent device without having to pass the API key and auth tokens to the UI. ![architecture](https://i.ibb.co/23qV2qf/dataflow-diagram.png) Web UI showing a real-time state of a single plant-based on the agent structure described above: ![screenshot](https://i.ibb.co/Y80wmd0/swim-ai.gif) > swim.ai provides in a separate project, a range of [UI widgets](https://www.npmjs.com/package/@swim/ux) to build your custom dashboards. The bridge now connected to Pelion notification channel, continuously feeding the changes to WebAgent, which in-turn update their internal state to represent the current device management view. The architecture of swim allows us to easily query this state, e.g. the history of a resource sensor value over time, apply analytical functions running continuously which in-turn may update the state of a different web agent which can then trigger a device management action. We've only scratched the surface on what is possible with swim.ai, utilizing a subset of the functionality provided. Head over to swim [github example](https://github.com/swimos/plant-monitor/tree/pelion) to testbed locally the Pelion integration as well as visit the [web site](https://www.swim.ai/) to learn more about the framework. The demo requires to have an account with [Pelion IoT platform](https://www.pelion.com/) but we provide [free-tier access](https://os.mbed.com/pelion-free-tier/) so you can easily [get started](https://www.pelion.com/guides/connect-device-to-pelion/). Have fun!