This commit is contained in:
Thomas Nordquist
2019-04-04 19:51:44 +02:00
parent c20c075bcf
commit 09dcce97b7
55 changed files with 775 additions and 1415 deletions

View File

@@ -6,7 +6,7 @@ import {
storageClearEvent,
storageLoadEvent,
storageStoreEvent,
makeStorageAcknowledgementEvent,
makeStorageAcknowledgementEvent
} from '../../events/StorageEvents'
export default class ConfigStorage {

View File

@@ -5,12 +5,12 @@ type MessageCallback = (topic: string, payload: Buffer) => void
// A DataSource should automatically reconnect if connection was broken
interface DataSource<DataSourceOptions> {
topicSeparator: string
stateMachine: DataSourceStateMachine
connect(options: DataSourceOptions): DataSourceStateMachine
disconnect(): void
onMessage(messageCallback: MessageCallback): void
publish(msg: MqttMessage): void
topicSeparator: string
stateMachine: DataSourceStateMachine
}
export { DataSource, MessageCallback }

View File

@@ -21,22 +21,6 @@ export class RingBuffer<T extends Lengthwise> {
}
}
public clone(): RingBuffer<T> {
return new RingBuffer(this.capacity, this.maxItems, this)
}
public toArray() {
return this.items.slice(this.start, this.end)
}
public add(item: T) {
const size = item.length
this.enforceCapacityConstraints(size)
this.usage += size
this.items[this.end] = item
this.end += 1
}
private enforceCapacityConstraints(addedItemSize: number) {
const remainingSize = this.capacity - (this.usage + addedItemSize)
if (remainingSize < 0) {
@@ -69,4 +53,20 @@ export class RingBuffer<T extends Lengthwise> {
const freedSpace = firstItem.length
this.usage -= freedSpace
}
public clone(): RingBuffer<T> {
return new RingBuffer(this.capacity, this.maxItems, this)
}
public toArray() {
return this.items.slice(this.start, this.end)
}
public add(item: T) {
const size = item.length
this.enforceCapacityConstraints(size)
this.usage += size
this.items[this.end] = item
this.end += 1
}
}

View File

@@ -53,7 +53,12 @@ export class Tree<ViewModel> extends TreeNode<ViewModel> {
super(undefined, undefined)
}
public updateWithConnection(emitter: EventBusInterface, connectionId: string, nodeFilter?:(node: TreeNode<ViewModel>) => boolean) {
private handleNewData = (msg: MqttMessage) => {
this.unmergedMessages.push(msg)
this.didReceive.dispatch()
}
public updateWithConnection(emitter: EventBusInterface, connectionId: string, nodeFilter?: (node: TreeNode<ViewModel>) => boolean) {
this.updateSource = emitter
this.connectionId = connectionId
this.nodeFilter = nodeFilter
@@ -82,11 +87,6 @@ export class Tree<ViewModel> extends TreeNode<ViewModel> {
return this.unmergedMessages
}
private handleNewData = (msg: MqttMessage) => {
this.unmergedMessages.push(msg)
this.didReceive.dispatch()
}
public stopUpdating() {
if (this.subscriptionEvent && this.updateSource) {
this.updateSource.unsubscribe(this.subscriptionEvent, this.handleNewData)

View File

@@ -8,7 +8,7 @@ export class TreeNode<ViewModel> {
public messageHistory: RingBuffer<Message> = new RingBuffer<Message>(3000, 100)
public viewModel?: ViewModel
public edges: {[s: string]: Edge<ViewModel>} = {}
public edgeArray: Edge<ViewModel>[] = []
public edgeArray: Array<Edge<ViewModel>> = []
public collapsed = false
public messages: number = 0
public lastUpdate: number = Date.now()
@@ -18,21 +18,10 @@ export class TreeNode<ViewModel> {
public isTree = false
private cachedPath?: string
private cachedChildTopics?: TreeNode<ViewModel>[]
private cachedChildTopics?: Array<TreeNode<ViewModel>>
private cachedLeafMessageCount?: number
private cachedChildTopicCount?: number
public unconnectedClone() {
const node = new TreeNode<ViewModel>()
node.message = this.message
node.mqttMessage = this.mqttMessage
node.messageHistory = this.messageHistory.clone()
node.messages = this.messages
node.lastUpdate = this.lastUpdate
return node
}
constructor(sourceEdge?: Edge<ViewModel>, message?: Message) {
if (sourceEdge) {
this.sourceEdge = sourceEdge
@@ -57,6 +46,70 @@ export class TreeNode<ViewModel> {
})
}
private previous(): TreeNode<ViewModel> | undefined {
return this.sourceEdge ? this.sourceEdge.source || undefined : undefined
}
private isTopicEmptyLeaf() {
const hasNoMessage = (!this.message || !this.message.value)
return hasNoMessage && this.isLeaf()
}
private isLeaf() {
return this.edgeArray.length === 0
}
private removeFromParent() {
const previous = this.previous()
if (!previous || !this.sourceEdge) {
return
}
previous.removeEdge(this.sourceEdge)
}
private findChild(edges: string[]): TreeNode<ViewModel> | undefined {
if (edges.length === 0) {
return this
}
const nextEdge = this.edges[edges[0]]
if (!nextEdge) {
return undefined
}
return nextEdge.target.findChild(edges.slice(1))
}
private mergeEdges(node: TreeNode<ViewModel>) {
const edgeKeys = Object.keys(node.edges)
let edgesDidUpdate = false
for (const edgeKey of edgeKeys) {
const matchingEdge = this.edges[edgeKey]
if (matchingEdge) {
matchingEdge.target.updateWithNode(node.edges[edgeKey].target)
} else {
this.addEdge(node.edges[edgeKey], false)
edgesDidUpdate = true
}
}
if (edgesDidUpdate) {
this.onEdgesChange.dispatch()
}
}
public unconnectedClone() {
const node = new TreeNode<ViewModel>()
node.message = this.message
node.mqttMessage = this.mqttMessage
node.messageHistory = this.messageHistory.clone()
node.messages = this.messages
node.lastUpdate = this.lastUpdate
return node
}
public setMessage(message: Message) {
this.messageHistory.add(message)
this.message = message
@@ -82,10 +135,6 @@ export class TreeNode<ViewModel> {
return this.cachedPath
}
private previous(): TreeNode<ViewModel> | undefined {
return this.sourceEdge ? this.sourceEdge.source || undefined : undefined
}
public addEdge(edge: Edge<ViewModel>, emitUpdate: boolean = false) {
this.edges[edge.name] = edge
this.edgeArray.push(edge)
@@ -96,7 +145,7 @@ export class TreeNode<ViewModel> {
}
}
public branch(): TreeNode<ViewModel>[] {
public branch(): Array<TreeNode<ViewModel>> {
const previous = this.previous()
if (!previous) {
return [this]
@@ -105,23 +154,6 @@ export class TreeNode<ViewModel> {
return previous.branch().concat([this])
}
private isTopicEmptyLeaf() {
const hasNoMessage = (!this.message || !this.message.value)
return hasNoMessage && this.isLeaf()
}
private isLeaf() {
return this.edgeArray.length === 0
}
private removeFromParent() {
const previous = this.previous()
if (!previous || !this.sourceEdge) {
return
}
previous.removeEdge(this.sourceEdge)
}
public removeEdge(edge: Edge<any>) {
delete this.edges[edge.name]
this.edgeArray = Object.values(this.edges)
@@ -171,7 +203,7 @@ export class TreeNode<ViewModel> {
return this.edgeArray.length
}
public childTopics(): TreeNode<ViewModel>[] {
public childTopics(): Array<TreeNode<ViewModel>> {
if (this.cachedChildTopics === undefined) {
const initialValue = this.message && this.message.value ? [this] : []
@@ -180,44 +212,12 @@ export class TreeNode<ViewModel> {
.reduce((a, b) => a.concat(b), initialValue)
}
return this.cachedChildTopics as TreeNode<ViewModel>[]
return this.cachedChildTopics as Array<TreeNode<ViewModel>>
}
public findNode (path: String): TreeNode<ViewModel> | undefined {
public findNode(path: String): TreeNode<ViewModel> | undefined {
const topics = path.split('/')
return this.findChild(topics)
}
private findChild(edges: string[]): TreeNode<ViewModel> | undefined {
if (edges.length === 0) {
return this
}
const nextEdge = this.edges[edges[0]]
if (!nextEdge) {
return undefined
}
return nextEdge.target.findChild(edges.slice(1))
}
private mergeEdges(node: TreeNode<ViewModel>) {
const edgeKeys = Object.keys(node.edges)
let edgesDidUpdate = false
for (const edgeKey of edgeKeys) {
const matchingEdge = this.edges[edgeKey]
if (matchingEdge) {
matchingEdge.target.updateWithNode(node.edges[edgeKey].target)
} else {
this.addEdge(node.edges[edgeKey], false)
edgesDidUpdate = true
}
}
if (edgesDidUpdate) {
this.onEdgesChange.dispatch()
}
}
}

View File

@@ -12,19 +12,12 @@ import {
makeConnectionStateEvent,
makePublishEvent,
removeConnection,
updateAvailable,
updateAvailable
} from '../../events'
export class ConnectionManager {
private connections: {[s: string]: DataSource<any>} = {}
public manageConnections() {
backendEvents.subscribe(addMqttConnectionEvent, this.handleConnectionRequest)
backendEvents.subscribe(removeConnection, (connectionId: string) => {
this.removeConnection(connectionId)
})
}
private handleConnectionRequest = (event: AddMqttConnection) => {
const connectionId = event.id
@@ -61,6 +54,13 @@ export class ConnectionManager {
})
}
public manageConnections() {
backendEvents.subscribe(addMqttConnectionEvent, this.handleConnectionRequest)
backendEvents.subscribe(removeConnection, (connectionId: string) => {
this.removeConnection(connectionId)
})
}
public removeConnection(conenctionId: string) {
const connection = this.connections[conenctionId]
if (connection) {