Plugin Documentation

IoTPulse
Realtime pub/sub with AWS IoT Core

Connect your game to AWS IoT Core over MQTT 5 and secure WebSockets: publish and subscribe in realtime, keep shared state in device shadows, and sign everything with the player's Amazon Cognito credentials - from Blueprints and C++.

v1.0
UE 4.27 & 5.8
Win64, Linux & Android
Category Networking
Alpha XP

Overview

IoTPulse gives Unreal Engine 4.27 and 5.8 games a managed realtime message bus without running servers: lobby chat, live events, presence, spectator feeds, remote configuration and companion apps all become MQTT topics on AWS IoT Core. Messages, connection events and results always arrive on the game thread.

  • Connect: MQTT 5 over a secure WebSocket (port 443), the handshake signed with AWS Signature V4 using the player's credentials.
  • Connect With Certificate: X.509 client certificate (mutual TLS) for kiosks and other fixed devices.
  • Publish, Subscribe with + / # wildcards, QoS 0 and 1, retained messages, last will, MQTT 5 request / response (response topic, correlation data) and user properties.
  • Automatic reconnect with exponential back-off; subscriptions are renewed when the broker lost the session.
  • Device shadows over HTTPS: Get Shadow, Update Shadow (reported or desired state, optimistic locking), Delete Shadow; realtime shadow updates over MQTT with Make Shadow Topic.
  • Publish (HTTPS) for one-off messages without a connection.
  • Amazon Cognito identity pools for guests and signed-in players; static keys and the default AWS chain for development and servers.

Requirements

RequirementDetails
Unreal Engine4.27 and 5.8
PlatformsWin64, Linux and Android
ModulesIoTPulse (Runtime), IoTPulseSdk (prebuilt AWS SDK for C++ 1.11.916 and the AWS Common Runtime in Source/ThirdParty)
DependenciesNo other plugins. On Linux and Android TLS trusts the root certificates of the engine's SSL module; HTTPS uses the engine's libcurl and OpenSSL.
AWSAn AWS account with AWS IoT Core and a Cognito identity pool. Messages, connection minutes and shadow operations are billed by AWS.

Installation

  1. Install IoTPulse from Fab into your engine, or copy the IoTPulse folder into your project's Plugins folder.
  2. Enable IoTPulse in Edit > Plugins and restart the editor.
  3. Open Project Settings > Plugins > IoTPulse and set Region, Identity Pool Id and IoT Data Endpoint.
  4. C++ only: add PublicDependencyModuleNames.Add("IoTPulse"); to your Build.cs.
Several AWS plugins in one projectEach Alpha XP cloud plugin carries its own copy of the SDK under a plugin-specific name, so they install side by side without conflicts.

Setting up AWS

  1. Find your account's IoT data endpoint: AWS IoT console > Settings > Device data endpoint, or aws iot describe-endpoint --endpoint-type iot:Data-ATS. It looks like a1b2c3d4e5f6g7-ats.iot.us-east-1.amazonaws.com; paste it into IoT Data Endpoint.
  2. In Amazon Cognito create an identity pool. Enable guest access if players may connect before signing in, and add your identity providers (for example a Cognito user pool).
  3. Edit the IAM role the pool gives to players (authenticated and/or guest). The example lets each player connect only with their own identity id as client id, use topics under mygame/ and the shadows of things named mygame-*:
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "iot:Connect",
      "Resource": "arn:aws:iot:us-east-1:123456789012:client/${cognito-identity.amazonaws.com:sub}"
    },
    {
      "Effect": "Allow",
      "Action": ["iot:Publish", "iot:Receive"],
      "Resource": [
        "arn:aws:iot:us-east-1:123456789012:topic/mygame/*",
        "arn:aws:iot:us-east-1:123456789012:topic/$aws/things/mygame-*/shadow/*"
      ]
    },
    {
      "Effect": "Allow",
      "Action": "iot:Subscribe",
      "Resource": [
        "arn:aws:iot:us-east-1:123456789012:topicfilter/mygame/*",
        "arn:aws:iot:us-east-1:123456789012:topicfilter/$aws/things/mygame-*/shadow/*"
      ]
    },
    {
      "Effect": "Allow",
      "Action": ["iot:GetThingShadow", "iot:UpdateThingShadow", "iot:DeleteThingShadow"],
      "Resource": "arn:aws:iot:us-east-1:123456789012:thing/mygame-*"
    }
  ]
}

Connect leaves the client id empty by default, which makes it the player's identity id - exactly what ${cognito-identity.amazonaws.com:sub} expands to. The same variable keeps per-player topics private, for example topic/mygame/players/${cognito-identity.amazonaws.com:sub}/*. Publish uses topic/ resources, Subscribe uses topicfilter/ resources (the filter exactly as written, wildcards included), Receive is checked for every delivered message.

Signed-in players also need an IoT policyFor authenticated Cognito identities AWS IoT Core checks two policies: the IAM role above and an AWS IoT policy attached to the identity itself. Create an IoT policy (AWS IoT console > Security > Policies) with the same statements and attach it to each identity id: aws iot attach-policy --policy-name MyGamePlayers --target us-east-1:01234567-89ab-.... AttachPolicy is an administrator operation: run it from your backend (for example a Lambda function called once after sign-up, using Get Identity Id), never grant iot:AttachPolicy to the player role. Guest (unauthenticated) identities only need the IAM role.
Never ship access keysStatic keys in the settings end up in DefaultGame.ini and in packaged games. Use them only for development and dedicated servers; players should always use the identity pool. Shipping builds refuse settings keys unless Allow Static Keys In Shipping is enabled.

Certificates (Connect With Certificate)

For kiosks and venue machines register the device as a thing in AWS IoT, create a certificate, attach an IoT policy to it and copy the certificate and private key (PEM) to the device. The client id is usually the thing name. Never put a device key into a game that players download.

Quick start

Lobby chat

  1. On Begin Play call Connect (defaults are fine). From On Connected store Connection in a variable.
  2. Bind On Message of the connection to a custom event and call Subscribe with mygame/lobby/42/chat.
  3. To send, call Publish on the connection: Topic mygame/lobby/42/chat, Payload {"from":"Ana","text":"gg"}.
  4. In the On Message event read Message > Payload (and Topic to tell channels apart; Topic Matches Filter helps with wildcards).
  5. On End Play call Disconnect.

Presence with a last will

Set Options > Will Topic to mygame/presence/<player>, Will Payload to {"online":false} and Will Retain on, then publish {"online":true} with Retain after connecting. If the game crashes or loses the network, AWS IoT Core publishes the will for you; a normal Disconnect does not.

Latent nodes

All latent nodes run in the background, can be stopped with Cancel on their return value and fire exactly one final pin on the game thread.

NodeInputsOutputsDescription
ConnectOptions, EndpointOn Connected / On Failure (Connection, Error)MQTT 5 over a secure WebSocket, signed with the plugin's credentials. Fails on the first refused attempt (wrong endpoint, policy, credentials); after that the connection reconnects by itself.
Connect With CertificateCertificate File, Private Key File, Options, EndpointOn Connected / On Failure (Connection, Error)Mutual TLS with an X.509 device certificate. Files are PEM; relative paths start at the project folder and packaged (non-asset) files are found too. The PEM text itself is accepted as well.
Publish And WaitConnection, Topic, Payload, Payload Bytes, QoS (default QoS 1), RetainOn Success / On Failure (Error)Publishes and waits for the broker's acknowledgement. On Failure covers "not authorized" (reason code 135), a stopped connection and the Ack Timeout.
Get ShadowThing Name, Shadow NameOn Success / On Not Found / On Failure (Shadow, Error)Reads a device shadow over HTTPS. Empty Shadow Name = the classic shadow.
Update ShadowThing Name, Shadow Name, Document, Section, Expected VersionOn Success / On Failure (Shadow, Error)Merges Document into state.reported (default) or state.desired, or sends a full document. Expected Version > 0 fails with ConflictException if somebody else changed the shadow first.
Delete ShadowThing Name, Shadow NameOn Success / On Failure (Error)Deletes a device shadow.
Publish (HTTPS)Topic, Payload, QoS, RetainOn Success / On Failure (Error)One message over HTTPS, no connection needed - for occasional events such as a match result.
Resolve IdentityForce RefreshOn Success / On Failure (Identity Id, Error)Fetches the Cognito identity and temporary credentials now, for example right after login, so Connect is fast and errors show up early.

Connection object

UIoTPulseConnection is returned by Connect. While it runs, the game instance keeps it alive; it is closed automatically when the game instance shuts down (end of Play In Editor, quitting). One object = one connection: after it stopped, call Connect again.

MemberKindDescription
PublishCallableTopic, Payload (UTF-8 text), QoS, Retain; advanced: Payload Bytes (binary, used when not empty), Response Topic, Correlation Data. Returns false if the message could not be queued. While reconnecting QoS 1 messages wait, QoS 0 messages are dropped.
SubscribeCallableTopic filter with + (one level) and # (the rest), QoS. The answer arrives on On Subscribed; the filter is renewed after reconnects.
UnsubscribeCallableStops a subscription.
DisconnectCallableSends DISCONNECT (the last will is not published) and stops reconnecting; On Stopped follows.
Is ConnectedPureTrue while the connection is up (false during a reconnect).
Get Client IdPureThe MQTT client id in use.
On MessageEventMessage: Topic, Payload, Payload Bytes, QoS, Retain, Response Topic, Correlation Data, Content Type, User Properties.
On Connection LostEventThe connection dropped (network, credentials expired, another client with the same id). It reconnects unless Auto Reconnect is off.
On ReconnectedEventConnected again; Session Present tells whether the broker kept the session.
On StoppedEventThe connection stopped for good (Disconnect, or a drop with Auto Reconnect off).
On SubscribedEventTopic Filter, Success, Granted QoS, Error - the broker's answer to Subscribe. A refused filter (not authorized) is not renewed.

Functions

NodeDescription
Set RegionSwitches the AWS region for every following connection and request.
Set Credential ModeOverrides the credential mode from the settings at runtime.
Set Login TokenSigns the player in to the identity pool with a provider token (Cognito user pool, Google, Apple, Facebook, OpenID). Connect again afterwards to use the new identity.
Clear Login TokensForgets all login tokens and the cached identity; the player becomes a guest.
Set Static CredentialsUses the given keys from now on (Static Keys mode), for example temporary keys handed out by your backend.
Get Identity IdThe player's Cognito identity id (the default client id); empty until credentials were resolved once.
Make User Pool Provider NameBuilds the login key of a Cognito user pool: cognito-idp.<region>.amazonaws.com/<pool id>.
Is ConfiguredReturns false and a reason when the endpoint or credentials are not set.
Make TopicJoins levels with "/": ["mygame", "lobby", "42"] becomes mygame/lobby/42.
Make Shadow TopicThe reserved MQTT topic of a shadow, for example $aws/things/mygame-lobby42/shadow/name/state/update/delta.
Topic Matches FilterTrue if a topic matches a filter with + and # wildcards (MQTT rules, case-sensitive).
CancelOn a latent node's return value: none of its pins fire any more.
Is FinishedOn a latent node's return value: true after it finished or was cancelled.

Device shadows

A shadow is a small JSON document that AWS IoT Core stores per thing: state.reported (what is), state.desired (what should be) and state.delta (the difference). Games use them for lobby state, server status boards, persistent room settings or companion-app controls.

  1. Create a thing (for example mygame-lobby42) in the AWS IoT console, or let your backend create one per room.
  2. Update Shadow with Document {"players":3,"map":"dunes"} writes state.reported. Set a field to null to remove it; Document null clears the section.
  3. Get Shadow returns the whole document plus Reported, Desired and Delta as JSON strings, and the Version for optimistic locking.
  4. Realtime: Subscribe to Make Shadow Topic with Topic = update/documents (every change) or update/delta (desired changes for a device).

Credentials

ModeUse forHow
Cognito Identity PoolGame clientsGuests get unauthenticated credentials; after Set Login Token the player gets the authenticated role. Credentials refresh automatically before they expire, also for reconnects.
Static KeysDevelopment, dedicated servers, keys from your backendSettings keys or Set Static Credentials (with an optional session token).
Default Credential ChainServers and toolsEnvironment variables, the ~/.aws profile, ECS and EC2 instance roles.
CertificateKiosks, fixed devicesConnect With Certificate; no AWS credentials involved.

C++ API

// Build.cs: PublicDependencyModuleNames.Add("IoTPulse");
#include "IoTPulseAsyncActions.h"
#include "IoTPulseConnection.h"

UIoTPulseConnectAction* Action = UIoTPulseConnectAction::Connect(this, FIoTPulseConnectOptions(), FString());
Action->OnConnected.AddDynamic(this, &AMyActor::HandleConnected);   // (UIoTPulseConnection*, const FIoTPulseError&)
Action->Activate();

void AMyActor::HandleConnected(UIoTPulseConnection* Connection, const FIoTPulseError& Error)
{
    Mqtt = Connection;                                         // UPROPERTY() UIoTPulseConnection* Mqtt;
    Mqtt->OnMessage.AddDynamic(this, &AMyActor::HandleMessage);
    Mqtt->Subscribe(TEXT("mygame/lobby/42/chat"));
    Mqtt->PublishWithCallback(TEXT("mygame/lobby/42/chat"), TEXT("{\"text\":\"hi\"}"), EIoTPulseQoS::AtLeastOnce,
        false, TArray<uint8>(), FString(), FString(),
        [](bool bOk, const FIoTPulseError& Result) { /* game thread */ });
}

Every latent node class (UIoTPulseGetShadowAction, ...) can be created through its static factory function; bind the delegates, then call Activate().

Types

TypeKindMembers
FIoTPulseConnectOptionsStructClient Id, Keep Alive Seconds, Clean Start, Session Expiry Seconds, Will Topic, Will Payload, Will QoS, Will Retain
FIoTPulseMessageStructTopic, Payload, Payload Bytes, QoS, Retain, Response Topic, Correlation Data, Content Type, User Properties
FIoTPulseShadowStructThing Name, Shadow Name, Json, Reported, Desired, Delta, Version, Timestamp
FIoTPulseErrorStructCode, Message, Http Status (or MQTT reason code), Retryable
EIoTPulseQoSEnumDefault (Project Settings), QoS 0 (At Most Once), QoS 1 (At Least Once)
EIoTPulseShadowSectionEnumReported State, Desired State, Full Document
EIoTPulseShadowTopicEnumupdate, update/accepted, update/rejected, update/delta, update/documents, get, get/accepted, get/rejected, delete, delete/accepted, delete/rejected
EIoTPulseCredentialModeEnumCognito Identity Pool, Static Keys, Default Credential Chain
UIoTPulseConnectionClassSee Connection object

Settings

Project Settings > Plugins > IoTPulse (saved to DefaultGame.ini). HTTPS requests use changes at once, MQTT connections with the next Connect.

SettingDefaultDescription
Regionus-east-1Region of your IoT endpoint and identity pool.
Credential ModeCognito Identity PoolCognito Identity Pool, Static Keys or Default Credential Chain.
Identity Pool Id(empty)For example us-east-1:01234567-89ab-cdef-0123-456789abcdef.
Allow Guest AccessOnUnauthenticated identities before Set Login Token. The pool must allow guest access too.
Access Key Id / Secret Access Key(empty)Static Keys mode. Saved in DefaultGame.ini - development and servers only.
Allow Static Keys In ShippingOffStatic keys from the settings are refused in Shipping builds unless enabled (dedicated servers).
IoT Data Endpoint(empty)Your account's endpoint, for example a1b2c3d4e5f6g7-ats.iot.us-east-1.amazonaws.com. Used for MQTT and HTTPS.
Keep Alive Seconds60MQTT keep-alive when Connect leaves it at 0 (AWS IoT Core accepts 30 - 1200).
Auto ReconnectOnReconnect after a drop. Off: a drop stops the connection.
Min / Max Reconnect Delay Ms1000 / 60000Exponential back-off with jitter between reconnect attempts.
Default QoSQoS 0Used when a node's QoS is Default.
Ack Timeout Seconds30Wait for the acknowledgement of a QoS 1 publish, subscribe or unsubscribe.
Request Timeout Ms / Connect Timeout Ms30000 / 5000HTTPS request limit; network connect limit (HTTPS and MQTT).
Max Retries3Automatic HTTPS retries with exponential back-off for throttling and transient errors.
Worker Threads4Background threads for HTTPS requests and connection setup.
Verify SSLOnHTTPS certificate checks. Only disable for a local emulator.
Log Sdk WarningsOnForwards SDK and runtime warnings to LogIoTPulse.

Troubleshooting

Error codeCause and fix
NotConfiguredSet the IoT Data Endpoint and the Identity Pool Id in Project Settings > Plugins > IoTPulse, or switch the credential mode.
AWS_ERROR_HTTP_WEBSOCKET_UPGRADE_FAILUREAWS refused the signed WebSocket handshake (HTTP 403): the role lacks iot:Connect for this client id, the region does not match the endpoint, or (signed-in players) no IoT policy is attached to the identity.
NotAuthorized (135)The broker refused a connect, subscribe or publish: check iot:Connect / iot:Subscribe (topicfilter) / iot:Publish (topic) / iot:Receive resources and the attached IoT policy.
Refused (142, session taken over)Another connection uses the same client id - every device of a player needs its own id (for example identity id + a suffix, allowed with client/${cognito-identity.amazonaws.com:sub}*).
NotAuthorizedExceptionGuest access is off on the identity pool, or a login token expired. Enable guest access or call Set Login Token with a fresh token.
ResourceNotFoundExceptionGet Shadow: the thing has no such shadow yet (On Not Found). Elsewhere: wrong thing name or endpoint.
ConflictExceptionUpdate Shadow with Expected Version: the shadow changed in between. Read it again and retry.
CertificateErrorConnect With Certificate could not read the certificate or key file (path relative to the project folder, PEM format).
UnavailableThe SDK library could not be loaded or the engine is shutting down. Check the Output Log for LogIoTPulse errors.

Credits

© 2026 Alpha XP — alphaxp.net · Support: support@alphaxp.net. Includes the AWS SDK for C++ and the AWS Common Runtime (Apache License 2.0). Built for Unreal Engine 4.27 and 5.8.