fix: fix ui updates
This commit is contained in:
@@ -28,10 +28,10 @@ interface Props {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function useUpdateNodeWhenNodeReceivesUpdates(node?: q.TreeNode<any>) {
|
function useUpdateNodeWhenNodeReceivesUpdates(node?: q.TreeNode<any>) {
|
||||||
const [lastUpdate, setLastUpdate] = useState(0)
|
const [, setLastUpdate] = useState(0)
|
||||||
const updateNode = useCallback(
|
const updateNode = useCallback(
|
||||||
throttle(() => {
|
throttle(() => {
|
||||||
setLastUpdate(Date.now())
|
setLastUpdate(node ? node.lastUpdate : 0)
|
||||||
}, 300),
|
}, 300),
|
||||||
[node]
|
[node]
|
||||||
)
|
)
|
||||||
@@ -52,7 +52,6 @@ function Sidebar(props: Props) {
|
|||||||
const { classes, tree, nodePath } = props
|
const { classes, tree, nodePath } = props
|
||||||
const node = usePollingToFetchTreeNode(tree, nodePath || '')
|
const node = usePollingToFetchTreeNode(tree, nodePath || '')
|
||||||
useUpdateNodeWhenNodeReceivesUpdates(node)
|
useUpdateNodeWhenNodeReceivesUpdates(node)
|
||||||
// console.log(node && node.path(), tree, nodePath)
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div id="Sidebar" className={classes.drawer}>
|
<div id="Sidebar" className={classes.drawer}>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import Popper from '@material-ui/core/Popper'
|
|||||||
import MenuItem from '@material-ui/core/MenuItem'
|
import MenuItem from '@material-ui/core/MenuItem'
|
||||||
import MenuList from '@material-ui/core/MenuList'
|
import MenuList from '@material-ui/core/MenuList'
|
||||||
import WarningRounded from '@material-ui/icons/WarningRounded'
|
import WarningRounded from '@material-ui/icons/WarningRounded'
|
||||||
import { IDecoder, decoders } from '../../../../../backend/src/Model/sparkplugb'
|
import { MessageDecoder, decoders } from '../../../decoders'
|
||||||
import { Tooltip } from '@material-ui/core'
|
import { Tooltip } from '@material-ui/core'
|
||||||
|
|
||||||
export const TopicTypeButton = (props: { node?: q.TreeNode<any> }) => {
|
export const TopicTypeButton = (props: { node?: q.TreeNode<any> }) => {
|
||||||
@@ -23,7 +23,7 @@ export const TopicTypeButton = (props: { node?: q.TreeNode<any> }) => {
|
|||||||
const [open, setOpen] = React.useState(false)
|
const [open, setOpen] = React.useState(false)
|
||||||
|
|
||||||
const selectOption = useCallback(
|
const selectOption = useCallback(
|
||||||
(decoder: IDecoder, format: string) => {
|
(decoder: MessageDecoder, format: string) => {
|
||||||
if (!node) {
|
if (!node) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -86,7 +86,7 @@ export const TopicTypeButton = (props: { node?: q.TreeNode<any> }) => {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function DecoderStatus({ node, decoder, format }: { node: q.TreeNode<any>; decoder: IDecoder; format: string }) {
|
function DecoderStatus({ node, decoder, format }: { node: q.TreeNode<any>; decoder: MessageDecoder; format: string }) {
|
||||||
const decoded = useMemo(() => {
|
const decoded = useMemo(() => {
|
||||||
return node.message?.payload && decoder.decode(node.message?.payload, format)
|
return node.message?.payload && decoder.decode(node.message?.payload, format)
|
||||||
}, [node.message, decoder, format])
|
}, [node.message, decoder, format])
|
||||||
|
|||||||
@@ -1,48 +1,5 @@
|
|||||||
import { Base64Message } from './Base64Message'
|
import { Base64Message } from '../../../backend/src/Model/Base64Message'
|
||||||
import { Decoder } from './Decoder'
|
import { MessageDecoder } from './MessageDecoder'
|
||||||
import { get } from 'sparkplug-payload'
|
|
||||||
var sparkplug = get('spBv1.0')
|
|
||||||
|
|
||||||
export interface IDecoder<T = string> {
|
|
||||||
/**
|
|
||||||
* Can be used to
|
|
||||||
* @param topic
|
|
||||||
*/
|
|
||||||
formats: T[]
|
|
||||||
canDecodeTopic?(topic: string): boolean
|
|
||||||
canDecodeData?(data: Base64Message): boolean
|
|
||||||
decode(input: Base64Message, format: T | string | undefined): Base64Message
|
|
||||||
}
|
|
||||||
|
|
||||||
export const SparkplugDecoder: IDecoder = {
|
|
||||||
formats: ['Sparkplug'],
|
|
||||||
canDecodeTopic(topic: string) {
|
|
||||||
return !!topic.match(/^spBv1\.0\/[^/]+\/[ND](DATA|CMD|DEATH|BIRTH)\/[^/]+(\/[^/]+)?$/u)
|
|
||||||
},
|
|
||||||
decode(input: Base64Message): Base64Message {
|
|
||||||
try {
|
|
||||||
const message = Base64Message.fromString(
|
|
||||||
JSON.stringify(
|
|
||||||
// @ts-ignore
|
|
||||||
sparkplug.decodePayload(new Uint8Array(input.toBuffer()))
|
|
||||||
)
|
|
||||||
)
|
|
||||||
message.decoder = Decoder.SPARKPLUG
|
|
||||||
return message
|
|
||||||
} catch {
|
|
||||||
const message = new Base64Message(undefined, 'Failed to decode sparkplugb payload')
|
|
||||||
message.decoder = Decoder.NONE
|
|
||||||
return message
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
export const StringDecoder: IDecoder = {
|
|
||||||
formats: ['string'],
|
|
||||||
decode(input: Base64Message): Base64Message {
|
|
||||||
return input
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
type BinaryFormats =
|
type BinaryFormats =
|
||||||
| 'int8'
|
| 'int8'
|
||||||
@@ -59,7 +16,7 @@ type BinaryFormats =
|
|||||||
/**
|
/**
|
||||||
* Binary decode primitive binary data type and arrays of these
|
* Binary decode primitive binary data type and arrays of these
|
||||||
*/
|
*/
|
||||||
export const BinaryDecoder: IDecoder<BinaryFormats> = {
|
export const BinaryDecoder: MessageDecoder<BinaryFormats> = {
|
||||||
formats: ['int8', 'int16', 'int32', 'int64', 'uint8', 'uint16', 'uint32', 'uint64', 'float', 'double'],
|
formats: ['int8', 'int16', 'int32', 'int64', 'uint8', 'uint16', 'uint32', 'uint64', 'float', 'double'],
|
||||||
decode(input: Base64Message, format: BinaryFormats): Base64Message {
|
decode(input: Base64Message, format: BinaryFormats): Base64Message {
|
||||||
const decodingOption = {
|
const decodingOption = {
|
||||||
@@ -89,5 +46,3 @@ export const BinaryDecoder: IDecoder<BinaryFormats> = {
|
|||||||
return Base64Message.fromString(JSON.stringify(str.length === 1 ? str[0] : str))
|
return Base64Message.fromString(JSON.stringify(str.length === 1 ? str[0] : str))
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export const decoders = [SparkplugDecoder, BinaryDecoder, StringDecoder] as const
|
|
||||||
12
app/src/decoders/MessageDecoder.ts
Normal file
12
app/src/decoders/MessageDecoder.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import { Base64Message } from '../../../backend/src/Model/Base64Message'
|
||||||
|
|
||||||
|
export interface MessageDecoder<T = string> {
|
||||||
|
/**
|
||||||
|
* Can be used to
|
||||||
|
* @param topic
|
||||||
|
*/
|
||||||
|
formats: T[]
|
||||||
|
canDecodeTopic?(topic: string): boolean
|
||||||
|
canDecodeData?(data: Base64Message): boolean
|
||||||
|
decode(input: Base64Message, format: T | string | undefined): Base64Message
|
||||||
|
}
|
||||||
28
app/src/decoders/SparkplugBDecoder.ts
Normal file
28
app/src/decoders/SparkplugBDecoder.ts
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import { Base64Message } from '../../../backend/src/Model/Base64Message'
|
||||||
|
import { Decoder } from '../../../backend/src/Model/Decoder'
|
||||||
|
import { get } from 'sparkplug-payload'
|
||||||
|
import { MessageDecoder } from './MessageDecoder'
|
||||||
|
var sparkplug = get('spBv1.0')
|
||||||
|
|
||||||
|
export const SparkplugDecoder: MessageDecoder = {
|
||||||
|
formats: ['Sparkplug'],
|
||||||
|
canDecodeTopic(topic: string) {
|
||||||
|
return !!topic.match(/^spBv1\.0\/[^/]+\/[ND](DATA|CMD|DEATH|BIRTH)\/[^/]+(\/[^/]+)?$/u)
|
||||||
|
},
|
||||||
|
decode(input: Base64Message): Base64Message {
|
||||||
|
try {
|
||||||
|
const message = Base64Message.fromString(
|
||||||
|
JSON.stringify(
|
||||||
|
// @ts-ignore
|
||||||
|
sparkplug.decodePayload(new Uint8Array(input.toBuffer()))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
message.decoder = Decoder.SPARKPLUG
|
||||||
|
return message
|
||||||
|
} catch {
|
||||||
|
const message = new Base64Message(undefined, 'Failed to decode sparkplugb payload')
|
||||||
|
message.decoder = Decoder.NONE
|
||||||
|
return message
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
9
app/src/decoders/StringDecoder.ts
Normal file
9
app/src/decoders/StringDecoder.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import { Base64Message } from '../../../backend/src/Model/Base64Message'
|
||||||
|
import { MessageDecoder } from './MessageDecoder'
|
||||||
|
|
||||||
|
export const StringDecoder: MessageDecoder = {
|
||||||
|
formats: ['string'],
|
||||||
|
decode(input: Base64Message): Base64Message {
|
||||||
|
return input
|
||||||
|
},
|
||||||
|
}
|
||||||
6
app/src/decoders/index.ts
Normal file
6
app/src/decoders/index.ts
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
import { StringDecoder } from './StringDecoder'
|
||||||
|
import { BinaryDecoder } from './BinaryDecoder'
|
||||||
|
import { SparkplugDecoder } from './SparkplugBDecoder'
|
||||||
|
export * from './MessageDecoder'
|
||||||
|
|
||||||
|
export const decoders = [SparkplugDecoder, BinaryDecoder, StringDecoder] as const
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import * as q from '../../../backend/src/Model'
|
import * as q from '../../../backend/src/Model'
|
||||||
import { Destroyable } from '../../../backend/src/Model/Destroyable'
|
import { Destroyable } from '../../../backend/src/Model/Destroyable'
|
||||||
import { IDecoder, decoders } from '../../../backend/src/Model/sparkplugb'
|
import { MessageDecoder, decoders } from '../decoders'
|
||||||
import { EventDispatcher } from '../../../events'
|
import { EventDispatcher } from '../../../events'
|
||||||
|
|
||||||
function findDecoder<T extends Destroyable>(node: q.TreeNode<T>): TopicDecoder | undefined {
|
function findDecoder<T extends Destroyable>(node: q.TreeNode<T>): TopicDecoder | undefined {
|
||||||
@@ -17,7 +17,7 @@ function findDecoder<T extends Destroyable>(node: q.TreeNode<T>): TopicDecoder |
|
|||||||
: undefined
|
: undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
type TopicDecoder = { decoder: IDecoder; format: string | undefined }
|
type TopicDecoder = { decoder: MessageDecoder; format: string | undefined }
|
||||||
|
|
||||||
export class TopicViewModel implements Destroyable {
|
export class TopicViewModel implements Destroyable {
|
||||||
private selected: boolean
|
private selected: boolean
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ export class Base64Message {
|
|||||||
return new Base64Message(Base64.encode(str))
|
return new Base64Message(Base64.encode(str))
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Raw message conversions ('uint8' | 'uint16' | 'uint32' | 'uint64' | 'int8' | 'int16' | 'int32' | 'int64' | 'float' | 'double') */
|
|
||||||
public format(type: TopicDataType = 'string'): [string, 'json' | undefined] {
|
public format(type: TopicDataType = 'string'): [string, 'json' | undefined] {
|
||||||
try {
|
try {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
|||||||
@@ -1,24 +1,8 @@
|
|||||||
import { Destroyable } from './Destroyable'
|
import { Destroyable } from './Destroyable'
|
||||||
import { Edge, Message, RingBuffer, MessageHistory } from './'
|
import { Edge, Message, RingBuffer, MessageHistory } from './'
|
||||||
import { EventDispatcher } from '../../../events'
|
import { EventDispatcher } from '../../../events'
|
||||||
import { IDecoder, decoders } from './sparkplugb'
|
|
||||||
import { Base64Message } from './Base64Message'
|
|
||||||
|
|
||||||
// export type TopicDataType = 'json' | 'string' | 'hex' | 'integer' | 'unsigned int' | 'floating point'
|
export type TopicDataType = 'string' | 'json' | 'hex'
|
||||||
export type TopicDataType =
|
|
||||||
| 'json'
|
|
||||||
| 'string'
|
|
||||||
| 'hex'
|
|
||||||
| 'uint8'
|
|
||||||
| 'uint16'
|
|
||||||
| 'uint32'
|
|
||||||
| 'uint64'
|
|
||||||
| 'int8'
|
|
||||||
| 'int16'
|
|
||||||
| 'int32'
|
|
||||||
| 'int64'
|
|
||||||
| 'float'
|
|
||||||
| 'double'
|
|
||||||
|
|
||||||
export class TreeNode<ViewModel extends Destroyable> {
|
export class TreeNode<ViewModel extends Destroyable> {
|
||||||
public sourceEdge?: Edge<ViewModel>
|
public sourceEdge?: Edge<ViewModel>
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import {
|
|||||||
makePublishEvent,
|
makePublishEvent,
|
||||||
removeConnection,
|
removeConnection,
|
||||||
} from '../../events'
|
} from '../../events'
|
||||||
import { SparkplugDecoder } from './Model/sparkplugb'
|
|
||||||
|
|
||||||
export class ConnectionManager {
|
export class ConnectionManager {
|
||||||
private connections: { [s: string]: DataSource<any> } = {}
|
private connections: { [s: string]: DataSource<any> } = {}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ registerCrashReporter()
|
|||||||
// const electronTelemetry = electronTelemetryFactory('9b0c8ca04a361eb8160d98c5', buildOptions)
|
// const electronTelemetry = electronTelemetryFactory('9b0c8ca04a361eb8160d98c5', buildOptions)
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
// disable-dev-shm-usage is required to run the debug console
|
||||||
app.commandLine.appendSwitch('--no-sandbox --disable-dev-shm-usage')
|
app.commandLine.appendSwitch('--no-sandbox --disable-dev-shm-usage')
|
||||||
app.whenReady().then(() => {
|
app.whenReady().then(() => {
|
||||||
backendRpc.on(makeOpenDialogRpc(), async request => {
|
backendRpc.on(makeOpenDialogRpc(), async request => {
|
||||||
@@ -69,8 +70,6 @@ async function createWindow() {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
console.log('icon path', iconPath)
|
|
||||||
mainWindow.webContents.openDevTools({ mode: 'detach' })
|
|
||||||
// Load the index.html of the app.
|
// Load the index.html of the app.
|
||||||
if (isDev()) {
|
if (isDev()) {
|
||||||
mainWindow.loadURL('http://localhost:8080')
|
mainWindow.loadURL('http://localhost:8080')
|
||||||
|
|||||||
Reference in New Issue
Block a user