From 4018499331b33e145abf128e13f31eeadd3f3c48 Mon Sep 17 00:00:00 2001 From: "Melton, Ryan" Date: Sat, 9 Jan 2021 14:11:53 -0700 Subject: [PATCH] Fix router status, tool initial load, preidentified protocol, empty set to complete for extractor --- lib/cosmos/api/interface_api.rb | 11 +-- lib/cosmos/api/router_api.rb | 18 ++-- lib/cosmos/interfaces/interface.rb | 4 +- .../protocols/preidentified_protocol.rb | 12 +-- .../microservices/interface_microservice.rb | 32 +++---- lib/cosmos/models/interface_status_model.rb | 16 ++-- lib/cosmos/models/model.rb | 1 - lib/cosmos/models/tool_model.rb | 64 +++++++------- lib/cosmos/topics/interface_topics.rb | 8 ++ lib/cosmos/topics/router_topics.rb | 8 ++ lib/cosmos/utilities/store.rb | 16 ---- web/cmd_tlm_api/app/models/screen.rb | 10 +-- web/cmd_tlm_api/app/models/streaming_api.rb | 13 +-- web/frontend/src/AppNav.vue | 28 +++--- .../src/tools/CmdTlmServer/RoutersTab.vue | 87 ++++++++++++++++--- 15 files changed, 194 insertions(+), 134 deletions(-) diff --git a/lib/cosmos/api/interface_api.rb b/lib/cosmos/api/interface_api.rb index 149f96851..a8c0f407a 100644 --- a/lib/cosmos/api/interface_api.rb +++ b/lib/cosmos/api/interface_api.rb @@ -19,6 +19,7 @@ require 'cosmos/models/interface_model' require 'cosmos/models/interface_status_model' +require 'cosmos/topics/interface_topics' module Cosmos module Api @@ -62,7 +63,7 @@ def get_interface_names(scope: $cosmos_scope, token: $cosmos_token) # @param params [Array] Parameters to pass to the interface. def connect_interface(interface_name, *params, scope: $cosmos_scope, token: $cosmos_token) authorize(permission: 'system_set', interface_name: interface_name, scope: scope, token: token) - Store.instance.write_interface(interface_name, {'connect' => true}, scope: scope) + InterfaceTopics.connect_interface(interface_name, scope: scope) end # Disconnects from an interface and kills its telemetry gathering thread @@ -70,7 +71,7 @@ def connect_interface(interface_name, *params, scope: $cosmos_scope, token: $cos # @param interface_name (see #connect_interface) def disconnect_interface(interface_name, scope: $cosmos_scope, token: $cosmos_token) authorize(permission: 'system_set', interface_name: interface_name, scope: scope, token: token) - Store.instance.write_interface(interface_name, {'disconnect' => true }, scope: scope) + InterfaceTopics.disconnect_interface(interface_name, scope: scope) end # @param interface_name (see #connect_interface) @@ -78,7 +79,7 @@ def disconnect_interface(interface_name, scope: $cosmos_scope, token: $cosmos_to # 'ATTEMPTING' or 'DISCONNECTED'. def interface_state(interface_name, scope: $cosmos_scope, token: $cosmos_token) authorize(permission: 'system', interface_name: interface_name, scope: scope, token: token) - CmdTlmServer.interfaces.state(interface_name) + InterfaceStatusModel.get(name: interface_name, scope: scope)['state'] end # Associates a target and all its commands and telemetry with a particular @@ -112,7 +113,7 @@ def get_interface_info(interface_name, scope: $cosmos_scope, token: $cosmos_toke authorize(permission: 'system', interface_name: interface_name, scope: scope, token: token) int = InterfaceStatusModel.get(name: interface_name, scope: scope) return [int['state'], int['clients'], int['txsize'], int['rxsize'], - int['txbytes'], int['rxbytes'], int['cmdcnt'], int['tlmcnt']] + int['txbytes'], int['rxbytes'], int['txcnt'], int['rxcnt']] end # Get information about all interfaces @@ -126,7 +127,7 @@ def get_all_interface_info(scope: $cosmos_scope, token: $cosmos_token) info = [] InterfaceStatusModel.all(scope: scope).each do |int_name, int| info << [int['name'], int['state'], int['clients'], int['txsize'], int['rxsize'], - int['txbytes'], int['rxbytes'], int['cmdcnt'], int['tlmcnt']] + int['txbytes'], int['rxbytes'], int['txcnt'], int['rxcnt']] end info.sort! {|a,b| a[0] <=> b[0] } info diff --git a/lib/cosmos/api/router_api.rb b/lib/cosmos/api/router_api.rb index 5d2244ec8..11e0a7596 100644 --- a/lib/cosmos/api/router_api.rb +++ b/lib/cosmos/api/router_api.rb @@ -19,6 +19,7 @@ require 'cosmos/models/router_model' require 'cosmos/models/router_status_model' +require 'cosmos/topics/router_topics' module Cosmos module Api @@ -46,8 +47,7 @@ def get_router_names(scope: $cosmos_scope, token: $cosmos_token) # @param params [Array] Parameters to pass to the router. def connect_router(router_name, *params, scope: $cosmos_scope, token: $cosmos_token) authorize(permission: 'system_set', router_name: router_name, scope: scope, token: token) - CmdTlmServer.routers.connect(router_name, *params) - nil + RouterTopics.connect_router(router_name, scope: scope) end # Disconnects a router and kills its command gathering thread @@ -55,8 +55,7 @@ def connect_router(router_name, *params, scope: $cosmos_scope, token: $cosmos_to # @param router_name (see #connect_router) def disconnect_router(router_name, scope: $cosmos_scope, token: $cosmos_token) authorize(permission: 'system_set', router_name: router_name, scope: scope, token: token) - CmdTlmServer.routers.disconnect(router_name) - nil + RouterTopics.disconnect_router(router_name, scope: scope) end # @param router_name (see #connect_router) @@ -64,10 +63,9 @@ def disconnect_router(router_name, scope: $cosmos_scope, token: $cosmos_token) # 'ATTEMPTING' or 'DISCONNECTED'. def router_state(router_name, scope: $cosmos_scope, token: $cosmos_token) authorize(permission: 'system', router_name: router_name, scope: scope, token: token) - CmdTlmServer.routers.state(router_name) + RouterStatusModel.get(name: router_name, scope: scope)['state'] end - # Get information about a router # # @param router_name [String] Router name @@ -77,7 +75,9 @@ def router_state(router_name, scope: $cosmos_scope, token: $cosmos_token) # Pkts sent] for the router def get_router_info(router_name, scope: $cosmos_scope, token: $cosmos_token) authorize(permission: 'system', router_name: router_name, scope: scope, token: token) - RouterStatusModel.get(name: router_name, scope: scope) + int = RouterStatusModel.get(name: router_name, scope: scope) + return [int['state'], int['clients'], int['txsize'], int['rxsize'], + int['txbytes'], int['rxbytes'], int['rxcnt'], int['txcnt']] end # Get information about all routers @@ -89,9 +89,9 @@ def get_router_info(router_name, scope: $cosmos_scope, token: $cosmos_token) def get_all_router_info(scope: $cosmos_scope, token: $cosmos_token) authorize(permission: 'system', scope: scope, token: token) info = [] - Store.instance.get_routers(scope: scope).each do |int| + RouterStatusModel.all(scope: scope).each do |int_name, int| info << [int['name'], int['state'], int['clients'], int['txsize'], int['rxsize'],\ - int['txbytes'], int['rxbytes'], int['cmdcnt'], int['tlmcnt']] + int['txbytes'], int['rxbytes'], int['rxcnt'], int['txcnt']] end info.sort! {|a,b| a[0] <=> b[0] } info diff --git a/lib/cosmos/interfaces/interface.rb b/lib/cosmos/interfaces/interface.rb index ecf90e421..8eb8fa3a0 100644 --- a/lib/cosmos/interfaces/interface.rb +++ b/lib/cosmos/interfaces/interface.rb @@ -315,8 +315,8 @@ def as_json config['rxsize'] = @read_queue_size config['txbytes'] = @bytes_written config['rxbytes'] = @bytes_read - config['cmdcnt'] = @write_count - config['tlmcnt'] = @read_count + config['txcnt'] = @write_count + config['rxcnt'] = @read_count config end diff --git a/lib/cosmos/interfaces/protocols/preidentified_protocol.rb b/lib/cosmos/interfaces/protocols/preidentified_protocol.rb index b1dcfcf83..2e5bd36cf 100644 --- a/lib/cosmos/interfaces/protocols/preidentified_protocol.rb +++ b/lib/cosmos/interfaces/protocols/preidentified_protocol.rb @@ -18,12 +18,14 @@ # copyright holder require 'cosmos/interfaces/protocols/burst_protocol' -require 'cosmos/packet_logs/packet_log_reader' module Cosmos # Delineates packets using the COSMOS preidentification system class PreidentifiedProtocol < BurstProtocol + COSMOS4_STORED_FLAG_MASK = 0x80 + COSMOS4_EXTRA_FLAG_MASK = 0x40 + # @param sync_pattern (see BurstProtocol#initialize) # @param max_length [Integer] The maximum allowed value of the length field # @param allow_empty_data [true/false/nil] See Protocol#initialize @@ -61,10 +63,10 @@ def write_packet(packet) @write_packet_name = 'UNKNOWN' unless @write_packet_name if @mode == 4 # COSMOS4.3+ Protocol @write_flags = 0 - @write_flags |= PacketLogReader::COSMOS4_STORED_FLAG_MASK if packet.stored + @write_flags |= COSMOS4_STORED_FLAG_MASK if packet.stored @write_extra = nil if packet.extra - @write_flags |= PacketLogReader::COSMOS4_EXTRA_FLAG_MASK + @write_flags |= COSMOS4_EXTRA_FLAG_MASK @write_extra = packet.extra.to_json end end @@ -141,9 +143,9 @@ def reduce_to_single_packet flags = @data[0].unpack('C')[0] # byte @data.replace(@data[1..-1]) @read_stored = false - @read_stored = true if (flags & PacketLogReader::COSMOS4_STORED_FLAG_MASK) != 0 + @read_stored = true if (flags & COSMOS4_STORED_FLAG_MASK) != 0 @read_extra = nil - if (flags & PacketLogReader::COSMOS4_EXTRA_FLAG_MASK) != 0 + if (flags & COSMOS4_EXTRA_FLAG_MASK) != 0 @reduction_state = :NEED_EXTRA else @reduction_state = :FLAGS_REMOVED diff --git a/lib/cosmos/microservices/interface_microservice.rb b/lib/cosmos/microservices/interface_microservice.rb index 7b62950a8..6ecf569ac 100644 --- a/lib/cosmos/microservices/interface_microservice.rb +++ b/lib/cosmos/microservices/interface_microservice.rb @@ -50,7 +50,7 @@ def start def run InterfaceTopics.receive_commands(@interface, scope: @scope) do |topic, msg_hash| # Check for a raw write to the interface - if topic =~ /CMDINTERFACE/ + if topic =~ /CMDINTERFACE/ or topic =~ /CMDROUTER/ if msg_hash['connect'] Logger.info "#{@interface.name}: Connect requested" @tlm.attempting() @@ -171,22 +171,24 @@ def run next 'SUCCESS' end - target_name = msg_hash["target_name"] - packet_name = msg_hash["packet_name"] + if @router.connected? + target_name = msg_hash["target_name"] + packet_name = msg_hash["packet_name"] - packet = System.telemetry.packet(target_name, packet_name) - packet.stored = ConfigParser.handle_true_false(msg_hash["stored"]) - packet.received_time = Time.from_nsec_from_epoch(msg_hash["time"].to_i) - packet.received_count = msg_hash["received_count"].to_i - packet.buffer = msg_hash["buffer"] + packet = System.telemetry.packet(target_name, packet_name) + packet.stored = ConfigParser.handle_true_false(msg_hash["stored"]) + packet.received_time = Time.from_nsec_from_epoch(msg_hash["time"].to_i) + packet.received_count = msg_hash["received_count"].to_i + packet.buffer = msg_hash["buffer"] - begin - @router.write(packet) - RouterStatusModel.set(@router.as_json, scope: @scope) - next 'SUCCESS' - rescue => e - Logger.error "#{@router.name}: #{e.formatted}" - next e.message + begin + @router.write(packet) + RouterStatusModel.set(@router.as_json, scope: @scope) + next 'SUCCESS' + rescue => e + Logger.error "#{@router.name}: #{e.formatted}" + next e.message + end end end end diff --git a/lib/cosmos/models/interface_status_model.rb b/lib/cosmos/models/interface_status_model.rb index 3bb1954d5..8f7f83a39 100644 --- a/lib/cosmos/models/interface_status_model.rb +++ b/lib/cosmos/models/interface_status_model.rb @@ -30,8 +30,8 @@ class InterfaceStatusModel < Model attr_accessor :rxsize attr_accessor :txbytes attr_accessor :rxbytes - attr_accessor :cmdcnt - attr_accessor :tlmcnt + attr_accessor :txcnt + attr_accessor :rxcnt def initialize( name:, @@ -41,8 +41,8 @@ def initialize( rxsize: 0, txbytes: 0, rxbytes: 0, - cmdcnt: 0, - tlmcnt: 0, + txcnt: 0, + rxcnt: 0, updated_at: nil, plugin: nil, scope:) @@ -58,8 +58,8 @@ def initialize( @rxsize = rxsize @txbytes = txbytes @rxbytes = rxbytes - @cmdcnt = cmdcnt - @tlmcnt = tlmcnt + @txcnt = txcnt + @rxcnt = rxcnt end def as_json @@ -71,8 +71,8 @@ def as_json 'rxsize' => @rxsize, 'txbytes' => @txbytes, 'rxbytes' => @rxbytes, - 'cmdcnt' => @cmdcnt, - 'tlmcnt' => @tlmcnt, + 'txcnt' => @txcnt, + 'rxcnt' => @rxcnt, 'plugin' => @plugin, 'updated_at' => @updated_at } diff --git a/lib/cosmos/models/model.rb b/lib/cosmos/models/model.rb index be15a228a..bc9168e04 100644 --- a/lib/cosmos/models/model.rb +++ b/lib/cosmos/models/model.rb @@ -49,7 +49,6 @@ def create(update: false, force: false) end end @updated_at = Time.now.to_nsec_from_epoch - STDOUT.puts @primary_key, @name, JSON.generate(self.as_json).to_s Store.hset(@primary_key, @name, JSON.generate(self.as_json)) end diff --git a/lib/cosmos/models/tool_model.rb b/lib/cosmos/models/tool_model.rb index a7214ac0c..19d2d7924 100644 --- a/lib/cosmos/models/tool_model.rb +++ b/lib/cosmos/models/tool_model.rb @@ -136,52 +136,52 @@ def self.unordered_all(scope: nil) if tools.length < 1 tools = {} tools['CmdTlmServer'] = { - name: 'CmdTlmServer', - icon: 'mdi-server-network', - url: '/cmd-tlm-server', - position: 1, + 'name' => 'CmdTlmServer', + 'icon' => 'mdi-server-network', + 'url' => '/cmd-tlm-server', + 'position' => 1, } tools['Limits Monitor'] = { - name: 'Limits Monitor', - icon: 'mdi-alert', - url: '/limits-monitor', - position: 2, + 'name' => 'Limits Monitor', + 'icon' => 'mdi-alert', + 'url' => '/limits-monitor', + 'position' => 2, } tools['Command Sender'] = { - name: 'Command Sender', - icon: 'mdi-satellite-uplink', - url: '/command-sender', - position: 3, + 'name' => 'Command Sender', + 'icon' => 'mdi-satellite-uplink', + 'url' => '/command-sender', + 'position' => 3, } tools['Script Runner'] = { - name: 'Script Runner', - icon: 'mdi-run-fast', - url: '/script-runner', - position: 4, + 'name' => 'Script Runner', + 'icon' => 'mdi-run-fast', + 'url' => '/script-runner', + 'position' => 4, } tools['Packet Viewer'] = { - name: 'Packet Viewer', - icon: 'mdi-format-list-bulleted', - url: '/packet-viewer', - position: 5, + 'name' => 'Packet Viewer', + 'icon' => 'mdi-format-list-bulleted', + 'url' => '/packet-viewer', + 'position' => 5, } tools['Telemetry Viewer'] = { - name: 'Telemetry Viewer', - icon: 'mdi-monitor-dashboard', - url: '/telemetry-viewer', - position: 6, + 'name' => 'Telemetry Viewer', + 'icon' => 'mdi-monitor-dashboard', + 'url' => '/telemetry-viewer', + 'position' => 6, } tools['Telemetry Grapher'] = { - name: 'Telemetry Grapher', - icon: 'mdi-chart-line', - url: '/telemetry-grapher', - position: 7, + 'name' => 'Telemetry Grapher', + 'icon' => 'mdi-chart-line', + 'url' => '/telemetry-grapher', + 'position' => 7, } tools['Data Extractor'] = { - name: 'Data Extractor', - icon: 'mdi-archive-arrow-down', - url: '/data-extractor', - position: 8, + 'name' => 'Data Extractor', + 'icon' => 'mdi-archive-arrow-down', + 'url' => '/data-extractor', + 'position' => 8, } tools.each do |name, tool| Store.hset("#{scope}__#{PRIMARY_KEY}", name, JSON.generate(tool)) diff --git a/lib/cosmos/topics/interface_topics.rb b/lib/cosmos/topics/interface_topics.rb index 014ba87f5..2fb6032d6 100644 --- a/lib/cosmos/topics/interface_topics.rb +++ b/lib/cosmos/topics/interface_topics.rb @@ -37,5 +37,13 @@ def self.receive_commands(interface, scope:) end end end + + def self.connect_interface(interface_name, scope:) + Store.write_topic("#{scope}__CMDINTERFACE__#{interface_name}", {'connect' => true}) + end + + def self.disconnect_interface(interface_name, scope:) + Store.write_topic("#{scope}__CMDINTERFACE__#{interface_name}", {'disconnect' => true}) + end end end \ No newline at end of file diff --git a/lib/cosmos/topics/router_topics.rb b/lib/cosmos/topics/router_topics.rb index 7ac29e727..1f288d259 100644 --- a/lib/cosmos/topics/router_topics.rb +++ b/lib/cosmos/topics/router_topics.rb @@ -54,5 +54,13 @@ def self.route_command(packet, target_names, scope:) end end + def self.connect_router(router_name, scope:) + Store.write_topic("#{scope}__CMDROUTER__#{router_name}", {'connect' => true}) + end + + def self.disconnect_router(router_name, scope:) + Store.write_topic("#{scope}__CMDROUTER__#{router_name}", {'disconnect' => true}) + end + end end \ No newline at end of file diff --git a/lib/cosmos/utilities/store.rb b/lib/cosmos/utilities/store.rb index ff574317d..36852520c 100644 --- a/lib/cosmos/utilities/store.rb +++ b/lib/cosmos/utilities/store.rb @@ -54,21 +54,6 @@ def initialize(pool_size = 10) @overrides = {} end - def write_interface(interface_name, hash, scope: $cosmos_scope) - @redis_pool.with do |redis| - if redis.hexists("#{scope}__cosmos_interface_status", interface_name) - write_topic("#{scope}__CMDINTERFACE__#{interface_name}", hash) - else - raise "Interface '#{interface_name}' does not exist" - end - end - end - - # TODO: Is this used anywhere? - # def cmd_interface(interface_name, target_name, cmd_name, cmd_params, range_check, hazardous_check, raw) - # write_topic("CMDINTERFACE__#{interface_name}", { 'target_name' => target_name, 'cmd_name' => cmd_name, 'cmd_params' => JSON.generate(cmd_params.as_json), 'range_check' => range_check, 'hazardous_check' => hazardous_check, 'raw' => raw }) - # end - def cmd_target(target_name, cmd_name, cmd_params, range_check, hazardous_check, raw, timeout_ms: 5000, scope: $cosmos_scope) cmd_packet_exist?(target_name, cmd_name, scope: scope) topic = "#{scope}__CMDTARGET__#{target_name}" @@ -76,7 +61,6 @@ def cmd_target(target_name, cmd_name, cmd_params, range_check, hazardous_check, update_topic_offsets([ack_topic]) cmd_id = write_topic(topic, { 'target_name' => target_name, 'cmd_name' => cmd_name, 'cmd_params' => JSON.generate(cmd_params.as_json), 'range_check' => range_check, 'hazardous_check' => hazardous_check, 'raw' => raw }) (timeout_ms / 100).times do - Logger.info "waiting for #{ack_topic}" read_topics([ack_topic], nil, 100) do |topic, msg_id, msg_hash, redis| if msg_hash["id"] == cmd_id # Logger.debug "Ack Received: #{msg_id}: #{msg_hash.inspect}" diff --git a/web/cmd_tlm_api/app/models/screen.rb b/web/cmd_tlm_api/app/models/screen.rb index ef96d2d1a..1e0c67189 100644 --- a/web/cmd_tlm_api/app/models/screen.rb +++ b/web/cmd_tlm_api/app/models/screen.rb @@ -17,15 +17,7 @@ # enterprise edition license of COSMOS if purchased from the # copyright holder -require 'aws-sdk-s3' - -Aws.config.update( - endpoint: ENV['COSMOS_S3_URL'] || ENV['COSMOS_DEVEL'] ? 'http://127.0.0.1:9000' : 'http://cosmos-minio:9000', - access_key_id: 'minioadmin', - secret_access_key: 'minioadmin', - force_path_style: true, - region: 'us-east-1' -) +require 'cosmos/utilities/s3' class Screen DEFAULT_BUCKET_NAME = 'config' diff --git a/web/cmd_tlm_api/app/models/streaming_api.rb b/web/cmd_tlm_api/app/models/streaming_api.rb index 3d37c88f4..3a2c89b3d 100644 --- a/web/cmd_tlm_api/app/models/streaming_api.rb +++ b/web/cmd_tlm_api/app/models/streaming_api.rb @@ -21,21 +21,13 @@ require 'fileutils' require 'cosmos' -require 'aws-sdk-s3' +require 'cosmos/utilities/s3' Cosmos.require_file 'cosmos/utilities/store' Cosmos.require_file 'cosmos/packets/json_packet' Cosmos.require_file 'cosmos/packet_logs/packet_log_reader' Cosmos.require_file 'cosmos/utilities/authorization' -Aws.config.update( - endpoint: ENV['COSMOS_S3_URL'] || ENV['COSMOS_DEVEL'] ? 'http://127.0.0.1:9000' : 'http://cosmos-minio:9000', - access_key_id: 'minioadmin', - secret_access_key: 'minioadmin', - force_path_style: true, - region: 'us-east-1' -) - class FileCacheFile attr_reader :s3_path attr_reader :local_path @@ -339,7 +331,7 @@ def redis_thread_body(topics, offsets, items_by_topic) # If we're no longer grabbing packets from the stream (empty result) # we check to see if we need to continue # Cosmos::Logger.debug "rtr:#{rtr} empty?:#{rtr.empty?} results:#{results} topics:#{topics} offsets:#{offsets}" - if rtr and rtr.empty? + if rtr.nil? or rtr.empty? topics.each do |topic| items = items_by_topic[topic] items.each do |item| @@ -354,6 +346,7 @@ def redis_thread_body(topics, offsets, items_by_topic) end end transmit_results(results, force: @collection.empty?) + transmit_results([], force: true) if !results.empty? and @collection.empty? else sleep(1) end diff --git a/web/frontend/src/AppNav.vue b/web/frontend/src/AppNav.vue index 2d54e89c5..edfbd357a 100644 --- a/web/frontend/src/AppNav.vue +++ b/web/frontend/src/AppNav.vue @@ -31,19 +31,24 @@ - - - {{ tool.icon }} - + + + + {{ tool.icon }} + + - {{ name }} + + {{ name }} + + + + mdi-arrow-top-right-thin-circle-outline + @@ -173,4 +178,7 @@ export default { /* For some reason the default margin-right is huge */ margin-right: 15px !important; } +.v-list-item__title { + color: white; +} diff --git a/web/frontend/src/tools/CmdTlmServer/RoutersTab.vue b/web/frontend/src/tools/CmdTlmServer/RoutersTab.vue index 463047d8a..513e25147 100644 --- a/web/frontend/src/tools/CmdTlmServer/RoutersTab.vue +++ b/web/frontend/src/tools/CmdTlmServer/RoutersTab.vue @@ -34,18 +34,26 @@ :headers="headers" :items="data" :search="search" + :custom-sort="sortTable" calculate-widths disable-pagination hide-default-footer multi-sort + data-test="routers-table" > @@ -64,6 +72,7 @@ export default { return { search: '', data: [], + buttonsDisabled: false, headers: [ { text: 'Name', value: 'name' }, { @@ -84,11 +93,64 @@ export default { } }, methods: { - interfaceConnect(name, connect) { - if (connect == 'Connect') { - this.api.connect_router(name) + // Custom sort algorithm to allow the connected column to be sorted by CONNECTED first + sortTable(items, index, isDesc) { + items.sort((a, b) => { + for (let i = 0; i < index.length; i++) { + let column = index[i] + let desc = isDesc[i] + + if (column === 'connected') { + // Items are the same so continue to let subsequent column sorts apply + if (a[column] === b[column]) { + continue + } + if (!desc) { + if (a[column] === 'CONNECTED') { + return -1 + } else { + return 1 + } + } else { + if (a[column] === 'CONNECTED') { + return 1 + } else { + return -1 + } + } + } else if (column === 'name') { + // Items are the same so continue to let subsequent column sorts apply + if (a[column] === b[column]) { + continue + } + if (!desc) { + // Strings so use localeCompare to sort + return a[column].localeCompare(b[column]) + } else { + return b[column].localeCompare(a[column]) + } + } else { + // Items are the same so continue to let subsequent column sorts apply + if (a[column] === b[column]) { + continue + } + if (!desc) { + // The rest of the columns are numbers so just subtract to sort + return a[column] - b[column] + } else { + return b[column] - a[column] + } + } + } + }) + return items + }, + connectDisconnect(item) { + this.buttonsDisabled = true + if (item.connected === 'DISCONNECTED') { + this.api.connect_router(item.name) } else { - this.api.disconnect_router(name) + this.api.disconnect_router(item.name) } }, update() { @@ -101,12 +163,12 @@ export default { if (int[1] == 'DISCONNECTED') { connect = 'Connect' connected_color = 'white' - } else if (int[1] == 'ATTEMPTING') { - connect = 'Cancel' - connected_color = 'red' - } else { + } else if (int[1] == 'CONNECTED') { connect = 'Disconnect' connected_color = 'green' + } else { + connect = 'Cancel' + connected_color = 'red' } this.data.push({ name: int[0], @@ -122,6 +184,7 @@ export default { tlm_pkts: int[8], }) } + this.buttonsDisabled = false }) }, },