Skip to content

Commit

Permalink
Merge branch 'master' into ecp-dropdown-menu
Browse files Browse the repository at this point in the history
# Conflicts:
#	src/viewProviders/OnlineDevicesViewProvider.ts
  • Loading branch information
MilapNaik committed Nov 1, 2023
2 parents 23cc45e + 316000b commit 4d55f59
Show file tree
Hide file tree
Showing 8 changed files with 539 additions and 122 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0



## [2.44.1](https://github.com/rokucommunity/vscode-brightscript-language/compare/v2.44.0...v2.44.1) - 2023-10-31
### Changed
- Enhance host picker during launch ([#512](https://github.com/rokucommunity/vscode-brightscript-language/pull/512))
- Add link for ECP registry ([#511](https://github.com/rokucommunity/vscode-brightscript-language/pull/511))
- Add brs to releases script ([5c6622b](https://github.com/rokucommunity/vscode-brightscript-language/commit/5c6622b))
- upgrade to [[email protected]](https://github.com/rokucommunity/roku-debug/blob/master/CHANGELOG.md#0208---2023-10-31). Notable changes since 0.20.7:
- Clean up control socket when it's closed ([roku-debug#166](https://github.com/rokucommunity/roku-debug/pull/166))



## [2.44.0](https://github.com/rokucommunity/vscode-brightscript-language/compare/v2.43.1...v2.44.0) - 2023-10-16
### Added
- ability to capture device screenshots ([#505](https://github.com/rokucommunity/vscode-brightscript-language/pull/505))
Expand Down
63 changes: 48 additions & 15 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "brightscript",
"displayName": "BrightScript Language",
"version": "2.44.0",
"version": "2.44.1",
"publisher": "RokuCommunity",
"description": "Language support for Roku's BrightScript language.",
"author": {
Expand Down Expand Up @@ -59,6 +59,7 @@
"brighterscript-formatter": "^1.6.34",
"debounce": "^1.2.0",
"dotenv": "^6.2.0",
"eventemitter3": "^5.0.1",
"fast-xml-parser": "^3.12.16",
"fs-extra": "^7.0.1",
"get-port": "^5.0.0",
Expand All @@ -71,7 +72,7 @@
"node-ssdp": "^4.0.0",
"postman-request": "^2.88.1-postman.32",
"pretty-bytes": "^5.6.0",
"roku-debug": "^0.20.7",
"roku-debug": "^0.20.8",
"roku-deploy": "^3.10.3",
"roku-test-automation": "^2.0.0-beta.20",
"semver": "^7.1.3",
Expand Down
97 changes: 83 additions & 14 deletions src/ActiveDeviceManager.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as backoff from 'backoff';
import { EventEmitter } from 'events';
import { EventEmitter } from 'eventemitter3';
import * as xmlParser from 'fast-xml-parser';
import * as http from 'http';
import * as NodeCache from 'node-cache';
Expand All @@ -8,13 +8,14 @@ import { Client } from 'node-ssdp';
import { URL } from 'url';
import { util } from './util';
import * as vscode from 'vscode';
import { firstBy } from 'thenby';
import type { Disposable } from 'vscode';

const DEFAULT_TIMEOUT = 10000;

export class ActiveDeviceManager extends EventEmitter {
export class ActiveDeviceManager {

constructor() {
super();
this.isRunning = false;
this.firstRequestForDevices = true;

Expand All @@ -38,23 +39,76 @@ export class ActiveDeviceManager extends EventEmitter {
this.deviceCache = new NodeCache({ stdTTL: 3600, checkperiod: 120 });
//anytime a device leaves the cache (either expired or manually deleted)
this.deviceCache.on('del', (deviceId, device) => {
this.emit('expiredDevice', deviceId, device);
void this.emit('device-expired', device);
});
this.processEnabledState();
}

private emitter = new EventEmitter();

public on(eventName: 'device-expired', handler: (device: RokuDeviceDetails) => void, disposables?: Disposable[]): () => void;
public on(eventName: 'device-found', handler: (device: RokuDeviceDetails) => void, disposables?: Disposable[]): () => void;
public on(eventName: string, handler: (payload: any) => void, disposables?: Disposable[]): () => void {
this.emitter.on(eventName, handler);
const unsubscribe = () => {
if (this.emitter !== undefined) {
this.emitter.removeListener(eventName, handler);
}
};

disposables?.push({
dispose: unsubscribe
});

return unsubscribe;
}

private async emit(eventName: 'device-expired', device: RokuDeviceDetails);
private async emit(eventName: 'device-found', device: RokuDeviceDetails);
private async emit(eventName: string, data?: any) {
//emit these events on next tick, otherwise they will be processed immediately which could cause issues
await util.sleep(0);
this.emitter?.emit(eventName, data);
}

public firstRequestForDevices: boolean;
public lastUsedDevice: string;
private enabled: boolean;
public lastUsedDevice: RokuDeviceDetails;
public enabled: boolean;
private showInfoMessages: boolean;
private deviceCache: NodeCache;
private exponentialBackoff: any;
private isRunning: boolean;

// Returns an object will all the active devices by device id
public getActiveDevices() {
/**
* Get a list of all devices discovered on the network
*/
public getActiveDevices(): RokuDeviceDetails[] {
this.firstRequestForDevices = false;
return this.deviceCache.mget(this.deviceCache.keys());
const devices = Object.values(
this.deviceCache.mget(this.deviceCache.keys()) as Record<string, RokuDeviceDetails>
).sort(firstBy((a: RokuDeviceDetails, b: RokuDeviceDetails) => {
return this.getPriorityForDeviceFormFactor(a) - this.getPriorityForDeviceFormFactor(b);
}).thenBy((a: RokuDeviceDetails, b: RokuDeviceDetails) => {
if (a.id < b.id) {
return -1;
}
if (a.id > b.id) {
return 1;
}
// ids must be equal
return 0;
}));
return devices;
}

private getPriorityForDeviceFormFactor(device: RokuDeviceDetails): number {
if (device.deviceInfo['is-stick']) {
return 0;
}
if (device.deviceInfo['is-tv']) {
return 2;
}
return 1;
}

// Returns the device cache statistics.
Expand Down Expand Up @@ -114,6 +168,18 @@ export class ActiveDeviceManager extends EventEmitter {
}
}

/**
* The number of milliseconds since a new device was discovered
*/
public get timeSinceLastDiscoveredDevice() {
if (!this.lastDiscoveredDeviceDate) {
return 0;
}
return Date.now() - this.lastDiscoveredDeviceDate.getTime();
}
private lastDiscoveredDeviceDate: Date;


// Discover all Roku devices on the network and watch for new ones that connect
private discoverAll(timeout: number = DEFAULT_TIMEOUT): Promise<string[]> {
return new Promise((resolve, reject) => {
Expand All @@ -122,13 +188,16 @@ export class ActiveDeviceManager extends EventEmitter {

finder.on('found', (device: RokuDeviceDetails) => {
if (!devices.includes(device.id)) {
if (this.showInfoMessages && this.deviceCache.get(device.id) === undefined) {
// New device found
void vscode.window.showInformationMessage(`Device found: ${device.deviceInfo['default-device-name']}`);
if (this.deviceCache.get(device.id) === undefined) {
this.lastDiscoveredDeviceDate = new Date();
if (this.showInfoMessages) {
// New device found
void vscode.window.showInformationMessage(`Device found: ${device.deviceInfo['default-device-name']}`);
}
}
this.deviceCache.set(device.id, device);
devices.push(device.id);
this.emit('foundDevice', device.id, device);
this.emit('device-found', device);
}
});

Expand Down Expand Up @@ -192,7 +261,7 @@ class RokuFinder extends EventEmitter {
const device: RokuDeviceDetails = {
location: url.origin,
ip: url.hostname,
id: info['device-info']['device-id'],
id: info['device-info']['device-id']?.toString?.(),
deviceInfo: info['device-info']
};
this.emit('found', device);
Expand Down
Loading

0 comments on commit 4d55f59

Please sign in to comment.