UI: Add support RPC request persistent parameter

This commit is contained in:
Vladyslav_Prykhodko 2021-07-09 19:27:50 +03:00 committed by Andrew Shvayka
parent 65032092e1
commit 8ce022b03c
5 changed files with 31 additions and 17 deletions

View File

@ -18,8 +18,8 @@
"resources": [], "resources": [],
"templateHtml": "<div style=\"height: 100%; overflow-y: auto;\" id=\"device-terminal\"></div>", "templateHtml": "<div style=\"height: 100%; overflow-y: auto;\" id=\"device-terminal\"></div>",
"templateCss": ".cmd .cursor.blink {\n -webkit-animation-name: terminal-underline;\n -moz-animation-name: terminal-underline;\n -ms-animation-name: terminal-underline;\n animation-name: terminal-underline;\n}\n.terminal .inverted, .cmd .inverted {\n border-bottom-color: #aaa;\n}\n\n", "templateCss": ".cmd .cursor.blink {\n -webkit-animation-name: terminal-underline;\n -moz-animation-name: terminal-underline;\n -ms-animation-name: terminal-underline;\n animation-name: terminal-underline;\n}\n.terminal .inverted, .cmd .inverted {\n border-bottom-color: #aaa;\n}\n\n",
"controllerScript": "var requestTimeout = 500;\n\nself.onInit = function() {\n var subscription = self.ctx.defaultSubscription;\n var rpcEnabled = subscription.rpcEnabled;\n var deviceName = 'Simulated';\n var prompt;\n if (subscription.targetDeviceName && subscription.targetDeviceName.length) {\n deviceName = subscription.targetDeviceName;\n }\n if (self.ctx.settings.requestTimeout) {\n requestTimeout = self.ctx.settings.requestTimeout;\n }\n var greetings = 'Welcome to ThingsBoard RPC debug terminal.\\n\\n';\n if (!rpcEnabled) {\n greetings += 'Target device is not set!\\n\\n';\n prompt = '';\n } else {\n greetings += 'Current target device for RPC commands: [[b;#fff;]' + deviceName + ']\\n\\n';\n greetings += 'Please type [[b;#fff;]\\'help\\'] to see usage.\\n';\n prompt = '[[b;#8bc34a;]' + deviceName +']> ';\n }\n \n var terminal = $('#device-terminal', self.ctx.$container).terminal(\n function(command) {\n if (command !== '') {\n try {\n var localCommand = command.trim();\n var requestUUID = uuidv4();\n if (localCommand === 'help') {\n printUsage(this);\n } else {\n var spaceIndex = localCommand.indexOf(' ');\n if (spaceIndex === -1 && !localCommand.length) {\n this.error(\"Wrong number of arguments!\");\n this.echo(' ');\n } else {\n var params;\n if (spaceIndex === -1) {\n spaceIndex = localCommand.length;\n }\n var name = localCommand.substr(0, spaceIndex);\n var args = localCommand.substr(spaceIndex + 1);\n if (args.length) {\n try {\n params = JSON.parse(args);\n } catch (e) {\n params = args;\n }\n }\n performRpc(this, name, params, requestUUID);\n }\n }\n } catch(e) {\n this.error(new String(e));\n }\n } else {\n this.echo('');\n }\n }, {\n greetings: greetings,\n prompt: prompt,\n enabled: rpcEnabled\n });\n \n if (!rpcEnabled) {\n terminal.error('No RPC target detected!').pause();\n }\n}\n\n\nfunction printUsage(terminal) {\n var commandsListText = '\\n[[b;#fff;]Usage:]\\n';\n commandsListText += ' <method> [params body]]\\n\\n';\n commandsListText += '[[b;#fff;]Example 1:]\\n'; \n commandsListText += ' myRemoteMethod1 myText\\n\\n'; \n commandsListText += '[[b;#fff;]Example 2:]\\n'; \n commandsListText += ' myOtherRemoteMethod \"{\\\\\"key1\\\\\": 2, \\\\\"key2\\\\\": \\\\\"myVal\\\\\"}\"\\n'; \n terminal.echo(new String(commandsListText));\n}\n\n\nfunction performRpc(terminal, method, params, requestUUID) {\n terminal.pause();\n self.ctx.controlApi.sendTwoWayCommand(method, params, requestTimeout, requestUUID).subscribe(\n function success(responseBody) {\n terminal.echo(JSON.stringify(responseBody));\n terminal.echo(' ');\n terminal.resume();\n },\n function fail() {\n var errorText = self.ctx.defaultSubscription.rpcErrorText;\n terminal.error(errorText);\n terminal.echo(' ');\n terminal.resume();\n }\n );\n}\n\n\nfunction uuidv4() {\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {\n var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);\n return v.toString(16);\n });\n}\n\n \nself.onDestroy = function() {\n}", "controllerScript": "var requestTimeout = 500;\nvar requestPersistent = false;\n\nself.onInit = function() {\n var subscription = self.ctx.defaultSubscription;\n var rpcEnabled = subscription.rpcEnabled;\n var deviceName = 'Simulated';\n var prompt;\n if (subscription.targetDeviceName && subscription.targetDeviceName.length) {\n deviceName = subscription.targetDeviceName;\n }\n if (self.ctx.settings.requestTimeout) {\n requestTimeout = self.ctx.settings.requestTimeout;\n }\n if (self.ctx.settings.requestPersistent) {\n requestPersistent = self.ctx.settings.requestPersistent;\n }\n var greetings = 'Welcome to ThingsBoard RPC debug terminal.\\n\\n';\n if (!rpcEnabled) {\n greetings += 'Target device is not set!\\n\\n';\n prompt = '';\n } else {\n greetings += 'Current target device for RPC commands: [[b;#fff;]' + deviceName + ']\\n\\n';\n greetings += 'Please type [[b;#fff;]\\'help\\'] to see usage.\\n';\n prompt = '[[b;#8bc34a;]' + deviceName +']> ';\n }\n \n var terminal = $('#device-terminal', self.ctx.$container).terminal(\n function(command) {\n if (command !== '') {\n try {\n var localCommand = command.trim();\n var requestUUID = uuidv4();\n if (localCommand === 'help') {\n printUsage(this);\n } else {\n var spaceIndex = localCommand.indexOf(' ');\n if (spaceIndex === -1 && !localCommand.length) {\n this.error(\"Wrong number of arguments!\");\n this.echo(' ');\n } else {\n var params;\n if (spaceIndex === -1) {\n spaceIndex = localCommand.length;\n }\n var name = localCommand.substr(0, spaceIndex);\n var args = localCommand.substr(spaceIndex + 1);\n if (args.length) {\n try {\n params = JSON.parse(args);\n } catch (e) {\n params = args;\n }\n }\n performRpc(this, name, params, requestUUID);\n }\n }\n } catch(e) {\n this.error(new String(e));\n }\n } else {\n this.echo('');\n }\n }, {\n greetings: greetings,\n prompt: prompt,\n enabled: rpcEnabled\n });\n \n if (!rpcEnabled) {\n terminal.error('No RPC target detected!').pause();\n }\n}\n\n\nfunction printUsage(terminal) {\n var commandsListText = '\\n[[b;#fff;]Usage:]\\n';\n commandsListText += ' <method> [params body]]\\n\\n';\n commandsListText += '[[b;#fff;]Example 1:]\\n'; \n commandsListText += ' myRemoteMethod1 myText\\n\\n'; \n commandsListText += '[[b;#fff;]Example 2:]\\n'; \n commandsListText += ' myOtherRemoteMethod \"{\\\\\"key1\\\\\": 2, \\\\\"key2\\\\\": \\\\\"myVal\\\\\"}\"\\n'; \n terminal.echo(new String(commandsListText));\n}\n\n\nfunction performRpc(terminal, method, params, requestUUID) {\n terminal.pause();\n self.ctx.controlApi.sendTwoWayCommand(method, params, requestTimeout, requestPersistent, requestUUID).subscribe(\n function success(responseBody) {\n terminal.echo(JSON.stringify(responseBody));\n terminal.echo(' ');\n terminal.resume();\n },\n function fail() {\n var errorText = self.ctx.defaultSubscription.rpcErrorText;\n terminal.error(errorText);\n terminal.echo(' ');\n terminal.resume();\n }\n );\n}\n\n\nfunction uuidv4() {\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {\n var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);\n return v.toString(16);\n });\n}\n\n \nself.onDestroy = function() {\n}",
"settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"Settings\",\n \"properties\": {\n \"requestTimeout\": {\n \"title\": \"RPC request timeout (ms)\",\n \"type\": \"number\",\n \"default\": 500\n }\n },\n \"required\": [\"requestTimeout\"]\n },\n \"form\": [\n \"requestTimeout\"\n ]\n}", "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"Settings\",\n \"properties\": {\n \"requestTimeout\": {\n \"title\": \"RPC request timeout (ms)\",\n \"type\": \"number\",\n \"default\": 500\n },\n \"requestPersistent\": {\n \"title\": \"RPC request persistent\",\n \"type\": \"boolean\",\n \"default\": false\n }\n },\n \"required\": [\"requestTimeout\"]\n },\n \"form\": [\n \"requestTimeout\",\n \"requestPersistent\"\n ]\n}",
"dataKeySettingsSchema": "{}\n", "dataKeySettingsSchema": "{}\n",
"defaultConfig": "{\"targetDeviceAliases\":[],\"showTitle\":true,\"backgroundColor\":\"#010101\",\"color\":\"rgba(255, 254, 254, 0.87)\",\"padding\":\"0px\",\"settings\":{\"parseGpioStatusFunction\":\"return body[pin] === true;\",\"gpioStatusChangeRequest\":{\"method\":\"setGpioStatus\",\"paramsBody\":\"{\\n \\\"pin\\\": \\\"{$pin}\\\",\\n \\\"enabled\\\": \\\"{$enabled}\\\"\\n}\"},\"requestTimeout\":500,\"switchPanelBackgroundColor\":\"#b71c1c\",\"gpioStatusRequest\":{\"method\":\"getGpioStatus\",\"paramsBody\":\"{}\"},\"gpioList\":[{\"pin\":1,\"label\":\"GPIO 1\",\"row\":0,\"col\":0,\"_uniqueKey\":0},{\"pin\":2,\"label\":\"GPIO 2\",\"row\":0,\"col\":1,\"_uniqueKey\":1},{\"pin\":3,\"label\":\"GPIO 3\",\"row\":1,\"col\":0,\"_uniqueKey\":2}]},\"title\":\"RPC debug terminal\",\"dropShadow\":true,\"enableFullscreen\":true,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}" "defaultConfig": "{\"targetDeviceAliases\":[],\"showTitle\":true,\"backgroundColor\":\"#010101\",\"color\":\"rgba(255, 254, 254, 0.87)\",\"padding\":\"0px\",\"settings\":{\"parseGpioStatusFunction\":\"return body[pin] === true;\",\"gpioStatusChangeRequest\":{\"method\":\"setGpioStatus\",\"paramsBody\":\"{\\n \\\"pin\\\": \\\"{$pin}\\\",\\n \\\"enabled\\\": \\\"{$enabled}\\\"\\n}\"},\"requestTimeout\":500,\"switchPanelBackgroundColor\":\"#b71c1c\",\"gpioStatusRequest\":{\"method\":\"getGpioStatus\",\"paramsBody\":\"{}\"},\"gpioList\":[{\"pin\":1,\"label\":\"GPIO 1\",\"row\":0,\"col\":0,\"_uniqueKey\":0},{\"pin\":2,\"label\":\"GPIO 2\",\"row\":0,\"col\":1,\"_uniqueKey\":1},{\"pin\":3,\"label\":\"GPIO 3\",\"row\":1,\"col\":0,\"_uniqueKey\":2}]},\"title\":\"RPC debug terminal\",\"dropShadow\":true,\"enableFullscreen\":true,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}"
} }

View File

@ -69,8 +69,8 @@ export interface WidgetSubscriptionApi {
} }
export interface RpcApi { export interface RpcApi {
sendOneWayCommand: (method: string, params?: any, timeout?: number, requestUUID?: string) => Observable<any>; sendOneWayCommand: (method: string, params?: any, timeout?: number, persistent?: boolean, requestUUID?: string) => Observable<any>;
sendTwoWayCommand: (method: string, params?: any, timeout?: number, requestUUID?: string) => Observable<any>; sendTwoWayCommand: (method: string, params?: any, timeout?: number, persistent?: boolean, requestUUID?: string) => Observable<any>;
} }
export interface IWidgetUtils { export interface IWidgetUtils {
@ -299,8 +299,8 @@ export interface IWidgetSubscription {
onResetTimewindow(): void; onResetTimewindow(): void;
updateTimewindowConfig(newTimewindow: Timewindow): void; updateTimewindowConfig(newTimewindow: Timewindow): void;
sendOneWayCommand(method: string, params?: any, timeout?: number, requestUUID?: string): Observable<any>; sendOneWayCommand(method: string, params?: any, timeout?: number, persistent?: boolean, requestUUID?: string): Observable<any>;
sendTwoWayCommand(method: string, params?: any, timeout?: number, requestUUID?: string): Observable<any>; sendTwoWayCommand(method: string, params?: any, timeout?: number, persistent?: boolean, requestUUID?: string): Observable<any>;
clearRpcError(): void; clearRpcError(): void;
subscribe(): void; subscribe(): void;

View File

@ -644,12 +644,12 @@ export class WidgetSubscription implements IWidgetSubscription {
} }
} }
sendOneWayCommand(method: string, params?: any, timeout?: number, requestUUID?: string): Observable<any> { sendOneWayCommand(method: string, params?: any, timeout?: number, persistent?: boolean, requestUUID?: string): Observable<any> {
return this.sendCommand(true, method, params, timeout, requestUUID); return this.sendCommand(true, method, params, timeout, persistent, requestUUID);
} }
sendTwoWayCommand(method: string, params?: any, timeout?: number, requestUUID?: string): Observable<any> { sendTwoWayCommand(method: string, params?: any, timeout?: number, persistent?: boolean, requestUUID?: string): Observable<any> {
return this.sendCommand(false, method, params, timeout, requestUUID); return this.sendCommand(false, method, params, timeout, persistent, requestUUID);
} }
clearRpcError(): void { clearRpcError(): void {
@ -658,7 +658,8 @@ export class WidgetSubscription implements IWidgetSubscription {
this.callbacks.onRpcErrorCleared(this); this.callbacks.onRpcErrorCleared(this);
} }
sendCommand(oneWayElseTwoWay: boolean, method: string, params?: any, timeout?: number, requestUUID?: string): Observable<any> { sendCommand(oneWayElseTwoWay: boolean, method: string, params?: any,
timeout?: number, persistent?: boolean, requestUUID?: string): Observable<any> {
if (!this.rpcEnabled) { if (!this.rpcEnabled) {
return throwError(new Error('Rpc disabled!')); return throwError(new Error('Rpc disabled!'));
} else { } else {
@ -670,6 +671,7 @@ export class WidgetSubscription implements IWidgetSubscription {
const requestBody: any = { const requestBody: any = {
method, method,
params, params,
persistent,
requestUUID requestUUID
}; };
if (timeout && timeout > 0) { if (timeout && timeout > 0) {

View File

@ -189,16 +189,16 @@ export class WidgetContext {
}; };
controlApi: RpcApi = { controlApi: RpcApi = {
sendOneWayCommand: (method, params, timeout, requestUUID) => { sendOneWayCommand: (method, params, timeout, persistent, requestUUID) => {
if (this.defaultSubscription) { if (this.defaultSubscription) {
return this.defaultSubscription.sendOneWayCommand(method, params, timeout, requestUUID); return this.defaultSubscription.sendOneWayCommand(method, params, timeout, persistent, requestUUID);
} else { } else {
return of(null); return of(null);
} }
}, },
sendTwoWayCommand: (method, params, timeout, requestUUID) => { sendTwoWayCommand: (method, params, timeout, persistent, requestUUID) => {
if (this.defaultSubscription) { if (this.defaultSubscription) {
return this.defaultSubscription.sendTwoWayCommand(method, params, timeout, requestUUID); return this.defaultSubscription.sendTwoWayCommand(method, params, timeout, persistent, requestUUID);
} else { } else {
return of(null); return of(null);
} }

View File

@ -126,7 +126,7 @@ export const timewindowCompletion: TbEditorCompletion = {
} }
} }
} }
} };
export const widgetContextCompletions: TbEditorCompletions = { export const widgetContextCompletions: TbEditorCompletions = {
ctx: { ctx: {
@ -465,6 +465,12 @@ export const widgetContextCompletions: TbEditorCompletions = {
description: 'Maximum delay in milliseconds to wait until response/acknowledgement is received.', description: 'Maximum delay in milliseconds to wait until response/acknowledgement is received.',
type: 'number', type: 'number',
optional: true optional: true
},
{
name: 'persistent',
description: 'RPC request persistent',
type: 'boolean',
optional: true
} }
], ],
return: { return: {
@ -492,6 +498,12 @@ export const widgetContextCompletions: TbEditorCompletions = {
description: 'Maximum delay in milliseconds to wait until response/acknowledgement is received.', description: 'Maximum delay in milliseconds to wait until response/acknowledgement is received.',
type: 'number', type: 'number',
optional: true optional: true
},
{
name: 'persistent',
description: 'RPC request persistent',
type: 'boolean',
optional: true
} }
], ],
return: { return: {
@ -657,4 +669,4 @@ export const widgetContextCompletions: TbEditorCompletions = {
...serviceCompletions ...serviceCompletions
} }
} }
} };