When you create a Cloud app, some events and commands are sent automatically. We call these standard events and commands.
You can also create your own custom events and commands. For example, you may want to listen for specific Key events that aren’t supported by default.
To add custom events and commands, you must modify the client (BrightScript).
To modify a specific BrightScript file, you must include it in the <project>/client
folder.
The original BrightScript files for the client are part of You.i Platform.
You can find these files in the ~/youiengine/<version>/src/cloud
folder.
Make sure to preserve the existing folder structure.
If you copy a file from ~/youiengine/<version>/src/cloud/source
, it must be pasted in <project>/client/source
.
For custom events we leverage the existing communication path and send our own custom JSON from the client using the sendObjectAsJSON
method.
Then the server has to listen for that custom event and respond appropriately.
Follow these steps to add custom events:
Copy the BrightScript files where you want to send the custom events inside the <project>/client
folder.
This example shows how to copy the main_implementation.brs
file.
Open a terminal window and run the following commands inside your <project>/client
folder:
mkdir source
cp ~/youiengine/<version>/src/cloud/source/main_implementation.brs ./source
Edit the <project>/client/source/main_implementation.brs
file to invoke the sendObjectAsJSON
method, passing an object with the custom event name and any additional parameters if needed.
Here’s how to send a custom event from a file inside the client/source
folder:
sendObjectAsJSON({ event: "CUSTOM_EVENT", payload: "PAYLOAD" })
This example shows how to copy the VideoPlayer.brs
file.
Copy the BrightScript file.
Open a terminal window and run the following command from your <project>/client
folder:
cp ~/youiengine/<version>/src/cloud/components/VideoPlayer.brs ./components
Adding custom events is straightforward if you modify a file in the client/source
folder.
However, the sendObjectAsJSON
method isn’t globally available for files in the client/components
folder.
In this situation, you need to make use of the Observer callback model provided by BrightScript.
Add an XML interface field by modifying the main_implementation.brs
file.
Copy the main_implementation.brs
from the source folder to the <project>/client
folder:
cd client
mkdir source
cp ~/youiengine/<version>/src/cloud/source/main_implementation.brs ./source
Edit the showSceneGraphScreen
method from the <project>/client/source/main_implementation.brs
file to add the following lines:
sub showSceneGraphScreen()
' ...
m.global.addField("customEvent", "assocarray", true)
m.global.ObserveField("customEvent", m.port)
'...
end sub
Observe the given field with a callback method.
Edit the processNodeEvent
method from the <project>/client/source/main_implementation.brs
file to add a new field handler callback:
function processNodeEvent(event as object) as boolean
fieldHandlers = {
' ...
"customEvent": onCustomEvent
}
' ...
end function
Write the callback method to handle the event.
Copy the customCommands.brs
file from the source folder to the <project>/client/source
folder:
cd client
cp ~/youiengine/<version>/src/cloud/source/customCommands.brs ./source
Add the field handler callback method inside the <project>/client/source/customCommands.brs
file:
REM Functions to run custom commands
sub initCustomCommands()
end sub
function onCustomEvent(event as object) as boolean
sendObjectAsJSON(event.GetData())
return true
end function
Mutate the global XML interface field to dispatch a message.
Edit the <project>/client/components/VideoPlayer.brs
file to dispatch the custom event.
Instead of using the sendObjectAsJSON
function, you should mutate the global customEvent
field, that will trigger the custom event callback.
m.global.customEvent = { event: "CUSTOM_EVENT", payload: "PAYLOAD" }
To side-load the client use the following command:
youi-tv roku-client -l -s <Roku device IP address> -u rokudev:<password>
Add two new files inside the <project>/youi/src
folder: CustomEvent.cpp
and CustomEvent.h
.
This example shows how to create CustomEvent.cpp
.
#include "CustomEvent.h"
#include <youireact/NativeModuleRegistry.h>
#ifdef YI_CLOUD_SERVER
#include <cloud/YiCloud.h>
#endif
static const std::string YI_EVENT_NAME = "CUSTOM_EVENT";
const CYIString ROKU_EVENT_NAME = "CUSTOM_EVENT";
YI_RN_INSTANTIATE_MODULE(CustomEvent, yi::react::EventEmitterModule);
YI_RN_REGISTER_MODULE(CustomEvent);
CustomEvent::CustomEvent()
{
SetSupportedEvents
({
YI_EVENT_NAME
});
#ifdef YI_CLOUD_SERVER
m_EventHandlerId = CYICloud::GetInterface().RegisterDataListener(
ROKU_EVENT_NAME,
[this](CYIString eventId, const yi::rapidjson::Document *pEvent) {
static_cast<void>(eventId);
CYIParsingError jsonError;
CYIString payload;
CYIRapidJSONUtility::GetStringField(pEvent, "payload", payload, jsonError);
EmitEvent(YI_EVENT_NAME, folly::dynamic::object("payload", ToDynamic(payload)));
return true;
});
#endif
}
CustomEvent::~CustomEvent() {
#ifdef YI_CLOUD_SERVER
CYICloud::GetInterface().UnregisterDataListener(ROKU_EVENT_NAME, m_EventHandlerId);
#endif
}
This example shows how to add CustomEvent.h
.
#include <youireact/modules/EventEmitter.h>
class YI_RN_MODULE(CustomEvent, yi::react::EventEmitterModule)
{
public:
CustomEvent();
~CustomEvent();
YI_RN_EXPORT_NAME(CustomEvent)
private:
uint64_t m_EventHandlerId;
};
Edit the <project>/youi/SourceList.cmake
file to add the CustomEvent.cpp
and CustomEvent.h
files.
Here’s an example SourceList.cmake
file:
# =============================================================================
# © You i Labs Inc. All rights reserved.
set (YI_PROJECT_SOURCE
src/App.cpp
src/AppFactory.cpp
src/CustomEvent.cpp
)
set (YI_PROJECT_HEADERS
src/App.h
src/CustomEvent.h
)
The following code sample shows how to handle a custom event:
import { NativeEventEmitter, NativeModules } from 'react-native';
const eventEmitter = new NativeEventEmitter(NativeModules.CustomEvent);
// ...
componentDidMount() {
this.eventSubscription = eventEmitter.addListener("CUSTOM_EVENT", (data) => {
console.log(`event: CUSTOM_EVENT, payload: ${data.payload}`);
});
}
componentWillUnmount() {
this.eventSubscription.remove();
}
Run the server. See Building and Running a Roku App.
You should see the following logs each time you send the custom event.
On the BrightScript Console:
[2021-12-02 04:50:38.201Z] Sending {"event":"CUSTOM_EVENT","payload":"PAYLOAD"} over TCP connection
On the server:
2021-12-01 20:50:23.226 rokuApp[39864:3091753] I/JavaScript: 1: event: CUSTOM_EVENT, payload: PAYLOAD
To add custom commands, you must modify the client and inject commands that can be invoked using the invokeCommand
method.
Enable the Cloud Solution through the Cloud Module.
Copy the customCommands.brs
file from the components folder to the <project/client>
folder.
cd client
mkdir source
cp ~/youiengine/<version>/src/cloud/source/customCommands.brs ./source
Create a new method inside the <project>/client/source/customCommands.brs
file.
Register the new command calling the addCustomCommand
method inside the initCustomCommands
method.
The following code sample shows how to handle a custom command:
REM Functions to run custom commands
sub initCustomCommands()
addCustomCommand("CUSTOM_COMMAND", handleCustomCommand)
end sub
sub handleCustomCommand(params as object)
logMessage("command: CUSTOM_COMMAND, payload: " + params.payload)
end sub
To side-load the client:
youi-tv roku-client -l -s <Roku IP address> -u rokudev:<password>
The following code sample shows how to send a custom event:
import { NativeModules} from "react-native";
const Cloud = NativeModules.Cloud;
// ...
Cloud.invokeCommand("CUSTOM_COMMAND", { payload: "PAYLOAD" });
After you register the custom command, you can use the invokeCommand
method from the Cloud API to send the new custom command.
The invokeCommand
method takes two parameters:
Note that the arguments must be JSON serializable.
They may contain only string
, int
, float
, and bool
elements.
Run the server. See Building and Running a Roku App.
You should see the following logs each time you invoke the custom command:
On the server:
2021-12-01 16:17:50.050 rokuApp[35151:3002180] I/ServerCommand: Sending command: (CUSTOM_COMMAND) at sequence: 232739048798.
On the BrightScript Console:
[2021-12-02 00:19:01.888Z] processCommand: CUSTOM_COMMAND
[2021-12-02 00:19:01.888Z] command: CUSTOM_COMMAND, payload: PAYLOAD