Skip to content

Commit 22ee259

Browse files
authored
feat: PE-616: Create JS example app for scanning bluetooth devices (#79)
- Add an example HTML and JS application that scans for Bluetooth devices - Updates from PR review - Add link to Wifi/Bluetooth modules datasheet - Add deduplication logic and more comments - Remove Ethernet / WiFi requirement from the Pre-requisites list - Add BT event parameters in method comment block for reference - Add more methods to transfer files to player - Also add telent/ssh doc link
1 parent 5b0f33d commit 22ee259

File tree

3 files changed

+248
-0
lines changed

3 files changed

+248
-0
lines changed
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# Bluetooth scan example on BrightSign players
2+
3+
## Introduction
4+
5+
The intention of this example is to show how to get a Bluetooth scanning application (HTML+JS) running on your BrightSign player.
6+
7+
The application is defined in `index.html` which also includes a `script` section for the JavaScript bits. There is an `autorun.brs` file which tells the player to run the application.
8+
9+
Note that this example cannot be ran on a browser as it uses BrightSign's proprietary JavaScript API.
10+
11+
## Prerequisites
12+
13+
1. **Bluetooth adapter**: The BrightSign player should have a Bluetooth adapter to scan for nearby devices. See [this page](https://www.brightsign.biz/wp-content/uploads/2023/04/Wifi-Modules-Bluetooth-Datasheet.pdf) for more information on BrightSign Wi-Fi and Bluetooth modules.
14+
15+
2. [optional] **Wi-Fi or Ethernet Network**: ONLY applicable if using the [Automated Transfer](#2-automated-transfer-using-brightsign-cli-for-dws) method below. Both your BrightSign player and the computer should be connected to the same Wi-Fi or Ethernet network.
16+
17+
## Steps to Set Up and Run the Application
18+
19+
After the application is ready to be deployed, you need to transfer the required files to your BrightSign player. There are 2 ways of doing this:
20+
21+
### 1. Manual Transfer
22+
1. Copy the `autorun.brs` and `index.html` files at the root of the SD card.
23+
2. Insert the SD card into the player.
24+
3. Reboot the player.
25+
26+
### 2. Automated Transfer Using BrightSign CLI for DWS
27+
BrightSign's player CLI: [player-CLI](https://www.npmjs.com/package/@brightsign/bsc). To deploy this app with the CLI:
28+
29+
Configure the CLI by choosing a name for your player and passing your player's information:
30+
31+
`bsc local player --add --player playerName --ip ip-address --user username --pass password --storage sd`
32+
33+
**Note**: The "username" and "password" are the credentials for the [Local DWS](#3-local-dws-ui) of the BrightSign player.
34+
35+
This is an example command for pushing files to your player:
36+
37+
`bsc local file --upload --player playerName --file ./path-to-your-file --destination sd/path-on-player`
38+
39+
### 3. Local DWS UI
40+
To access the Local DWS, go to the IP address of your player in a web browser. The default username is `"admin"` and the password is the player serial number.
41+
42+
**Note**: If you don't know the IP address of the player, you can boot up the player WITHOUT an SD card, and after a few seconds, the splash screen will display it, along with the player's serial number and OS version.
43+
44+
1. Once logged in to the DWS, go to the `SD` tab.
45+
2. Click on the `Browse` button in the `Upload Files` section.
46+
3. Select the `autorun.brs` and `index.html` files from your computer.
47+
4. Click on the `Upload` button to transfer the files to the player.
48+
5. Once the files are uploaded, you can reboot the player to run the application.
49+
6. You can also reboot the player using the `Reboot` button under the `Control` tab.
50+
51+
## Troubleshooting
52+
53+
- **No HTML content**: If you don't see anything on the display attached to the player, verify that:
54+
- The BrightSign player is connected to a display via an HDMI cable.
55+
- The required files are correctly copied to the root of the SD card.
56+
57+
- **Bluetooth scanning not working**: If the Bluetooth scanning is not working, verify that:
58+
- The BrightSign player has a Bluetooth adapter attached.
59+
- The player is at least on OS v9.0.199.
60+
61+
In order to troubleshoot any issues, it is recommended to use the BrightSign Shell. The shell can be accessed by connecting a serial cable to the BrightSign player and using a terminal emulator (e.g. PuTTY) to connect to the player. More details can be found [here](https://docs.brightsign.biz/space/DOC/1988100153/BrightSign+Shell).
62+
63+
If a serial cable is not available, you can make use of [telnet or SSH](https://docs.brightsign.biz/space/DOC/370673607/Telnet+and+SSH) as well.
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
function main()
2+
' This interface is the preferred way for JavaScript content to communicate with its parent application.
3+
' https://brightsign.atlassian.net/wiki/x/-gAeG
4+
mp = CreateObject("roMessagePort")
5+
6+
' Create HTML Widget which is defined below in its own function
7+
widget = CreateHTMLWidget(mp)
8+
widget.Show()
9+
10+
' Event Loop to view the events that are being sent from the HTML content.
11+
' The roHtmlWidgetEvent object is sent to the message port when an event occurs in the HTML content.
12+
while true
13+
msg = wait(0,mp)
14+
print "msg received - type=";type(msg)
15+
if type(msg) = "roHtmlWidgetEvent" then
16+
print "msg: ";msg
17+
end if
18+
end while
19+
end function
20+
21+
function CreateHTMLWidget(mp as object) as object
22+
' Get Screen Resolution
23+
' https://brightsign.atlassian.net/wiki/x/SQUYFg
24+
vidmode = CreateObject("roVideoMode")
25+
width = vidmode.GetResX()
26+
height = vidmode.GetResY()
27+
28+
' https://brightsign.atlassian.net/wiki/x/HwUYFg
29+
r = CreateObject("roRectangle",0,0,width,height)
30+
31+
' Create HTML Widget config
32+
' https://brightsign.atlassian.net/wiki/spaces/DOC/pages/370672896/roHtmlWidget#Initialization-Parameters
33+
config = {
34+
nodejs_enabled: true
35+
url: "file:///sd:/index.html"
36+
port: mp
37+
}
38+
39+
' Create HTML Widget
40+
' https://brightsign.atlassian.net/wiki/x/AAUYFg
41+
h = CreateObject("roHtmlWidget",r,config)
42+
return h
43+
end function
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
4+
<head>
5+
<meta charset="UTF-8" />
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
7+
<title>Bluetooth Device Scanning App</title>
8+
<style>
9+
/* CSS to style the background image and text */
10+
html,
11+
body {
12+
height: 100%;
13+
margin: 0;
14+
font-family: Arial, sans-serif;
15+
background: rgb(16, 9, 34);
16+
background: linear-gradient(90deg,
17+
rgba(48, 27, 105, 1) 0%,
18+
rgba(16, 9, 34, 1) 38%);
19+
color: white;
20+
padding: 16px;
21+
}
22+
</style>
23+
</head>
24+
25+
<body>
26+
<div class="background-img">
27+
<h1>Success!</h1>
28+
<p>
29+
Scanning for Bluetooth devices...
30+
Found <span id="bt-devices">0</span> unique devices.
31+
Found <span id="bt-adv-events">0</span> unique advertising reports.
32+
</p>
33+
</div>
34+
35+
<script>
36+
const bt = require('@brightsign/bt');
37+
const btc = new bt();
38+
let count = 0;
39+
let advCount = 0;
40+
const seenAdvReports = new Set();
41+
const seenDevices = new Set();
42+
43+
/**
44+
* advertising-report event listener for Bluetooth events.
45+
* Event contains the following parameters:
46+
*
47+
* interface BtCentralAdvertisingReportEvent {
48+
* attribute String adapter_path;
49+
* attribute String device_address;
50+
* attribute int rssi;
51+
* attribute Array<byte> data;
52+
* };
53+
*/
54+
btc.addEventListener('advertising-report', (event) => {
55+
// It is NOT recommended to log the whole event for production scenarios
56+
// since the logs are too verbose and may block the main thread.
57+
58+
// The following logic only logs parameters of unique events.
59+
if (event.detail) {
60+
const eventKey = `${event.detail.adapter_path}-${event.detail.device_address}`;
61+
if (!seenAdvReports.has(eventKey)) {
62+
seenAdvReports.add(eventKey);
63+
const msg = 'adapter_path: ' + event.detail.adapter_path +
64+
', device_address: ' + event.detail.device_address +
65+
', rssi: ' + event.detail.rssi +
66+
', data: ' + event.detail.data;
67+
68+
console.log('New event found: ' + msg);
69+
advCount++;
70+
document.getElementById('bt-adv-events').textContent = advCount;
71+
72+
} else {
73+
// Duplicate event ignored
74+
}
75+
} else {
76+
console.log('advertising-report event detail is invalid:', event);
77+
}
78+
});
79+
80+
/**
81+
* device-found event listener for Bluetooth devices.
82+
* Event contains the following parameters:
83+
*
84+
* interface BtCentralDeviceFoundEvent {
85+
* attribute String adapter_path;
86+
* attribute String address;
87+
* attribute String alias;
88+
* [optional] attribute String name;
89+
* [optional] attribute int rssi;
90+
* [optional] attribute int tx_power;
91+
* [optional] attribute Array<String> uuids;
92+
* [optional] attribute Array<byte> advertising_flags;
93+
* [optional] attribute Array<Array<int, Array<byte>>> manufacturer_data;
94+
* [optional] attribute Map<String, Array<byte>> service_data;
95+
* };
96+
*/
97+
btc.addEventListener('device-found', (event) => {
98+
// Note that "event" may contain duplicate device information.
99+
// The following code block ensures that only unique devices are logged.
100+
if (event.detail) {
101+
const deviceKey = `${event.detail.adapter_path}-${event.detail.device_address}`;
102+
if (!seenDevices.has(deviceKey)) {
103+
seenDevices.add(deviceKey);
104+
console.log('== new device-found: ' + JSON.stringify(event));
105+
count++;
106+
document.getElementById('bt-devices').textContent = count;
107+
} else {
108+
// Duplicate device ignored
109+
}
110+
} else {
111+
console.log('device-found event detail is invalid:', event);
112+
}
113+
});
114+
115+
/**
116+
* device-lost event listener for Bluetooth devices.
117+
* Event contains the following parameters:
118+
*
119+
* interface BtCentralDeviceLostEvent {
120+
* attribute String adapter_path;
121+
* attribute String device_address;
122+
* };
123+
*/
124+
btc.addEventListener('device-lost', (event) => {
125+
if (event.detail) {
126+
const deviceKey = `${event.detail.adapter_path}-${event.detail.device_address}`;
127+
if (seenDevices.has(deviceKey)) {
128+
seenDevices.delete(deviceKey);
129+
console.log('== device-lost: ' + JSON.stringify(event));
130+
count--;
131+
document.getElementById('bt-devices').textContent = count;
132+
}
133+
} else {
134+
console.log('device-lost event detail is invalid:', event);
135+
}
136+
});
137+
138+
btc.scan({ advertisingReports: true });
139+
</script>
140+
</body>
141+
142+
</html>

0 commit comments

Comments
 (0)