fix: fix ui updates
This commit is contained in:
@@ -28,10 +28,10 @@ interface Props {
|
||||
}
|
||||
|
||||
function useUpdateNodeWhenNodeReceivesUpdates(node?: q.TreeNode<any>) {
|
||||
const [lastUpdate, setLastUpdate] = useState(0)
|
||||
const [, setLastUpdate] = useState(0)
|
||||
const updateNode = useCallback(
|
||||
throttle(() => {
|
||||
setLastUpdate(Date.now())
|
||||
setLastUpdate(node ? node.lastUpdate : 0)
|
||||
}, 300),
|
||||
[node]
|
||||
)
|
||||
@@ -52,7 +52,6 @@ function Sidebar(props: Props) {
|
||||
const { classes, tree, nodePath } = props
|
||||
const node = usePollingToFetchTreeNode(tree, nodePath || '')
|
||||
useUpdateNodeWhenNodeReceivesUpdates(node)
|
||||
// console.log(node && node.path(), tree, nodePath)
|
||||
|
||||
return (
|
||||
<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 MenuList from '@material-ui/core/MenuList'
|
||||
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'
|
||||
|
||||
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 selectOption = useCallback(
|
||||
(decoder: IDecoder, format: string) => {
|
||||
(decoder: MessageDecoder, format: string) => {
|
||||
if (!node) {
|
||||
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(() => {
|
||||
return node.message?.payload && decoder.decode(node.message?.payload, format)
|
||||
}, [node.message, decoder, format])
|
||||
|
||||
48
app/src/decoders/BinaryDecoder.ts
Normal file
48
app/src/decoders/BinaryDecoder.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
import { Base64Message } from '../../../backend/src/Model/Base64Message'
|
||||
import { MessageDecoder } from './MessageDecoder'
|
||||
|
||||
type BinaryFormats =
|
||||
| 'int8'
|
||||
| 'int16'
|
||||
| 'int32'
|
||||
| 'int64'
|
||||
| 'uint8'
|
||||
| 'uint16'
|
||||
| 'uint32'
|
||||
| 'uint64'
|
||||
| 'float'
|
||||
| 'double'
|
||||
|
||||
/**
|
||||
* Binary decode primitive binary data type and arrays of these
|
||||
*/
|
||||
export const BinaryDecoder: MessageDecoder<BinaryFormats> = {
|
||||
formats: ['int8', 'int16', 'int32', 'int64', 'uint8', 'uint16', 'uint32', 'uint64', 'float', 'double'],
|
||||
decode(input: Base64Message, format: BinaryFormats): Base64Message {
|
||||
const decodingOption = {
|
||||
int8: [Buffer.prototype.readInt8, 1],
|
||||
int16: [Buffer.prototype.readInt16LE, 2],
|
||||
int32: [Buffer.prototype.readInt32LE, 4],
|
||||
int64: [Buffer.prototype.readBigInt64LE, 8],
|
||||
uint8: [Buffer.prototype.readUint8, 1],
|
||||
uint16: [Buffer.prototype.readUint16LE, 2],
|
||||
uint32: [Buffer.prototype.readUint32LE, 4],
|
||||
uint64: [Buffer.prototype.readBigUint64LE, 8],
|
||||
float: [Buffer.prototype.readFloatLE, 4],
|
||||
double: [Buffer.prototype.readDoubleLE, 8],
|
||||
} as const
|
||||
|
||||
const [readNumber, bytesToRead] = decodingOption[format]
|
||||
|
||||
const buf = input.toBuffer()
|
||||
let str: String[] = []
|
||||
if (buf.length % bytesToRead !== 0) {
|
||||
return new Base64Message(undefined, 'Data type does not align with message')
|
||||
}
|
||||
for (let index = 0; index < buf.length; index += bytesToRead) {
|
||||
str.push((readNumber as any).apply(buf, [index]).toString())
|
||||
}
|
||||
|
||||
return Base64Message.fromString(JSON.stringify(str.length === 1 ? str[0] : str))
|
||||
},
|
||||
}
|
||||
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 { Destroyable } from '../../../backend/src/Model/Destroyable'
|
||||
import { IDecoder, decoders } from '../../../backend/src/Model/sparkplugb'
|
||||
import { MessageDecoder, decoders } from '../decoders'
|
||||
import { EventDispatcher } from '../../../events'
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
type TopicDecoder = { decoder: IDecoder; format: string | undefined }
|
||||
type TopicDecoder = { decoder: MessageDecoder; format: string | undefined }
|
||||
|
||||
export class TopicViewModel implements Destroyable {
|
||||
private selected: boolean
|
||||
|
||||
Reference in New Issue
Block a user