2020-07-31 00:39:02 -04:00
|
|
|
/**
|
|
|
|
* WIN System Log Tail / Who's Talking?
|
|
|
|
*
|
|
|
|
* @author Rob Vella KK9ROB <me@robvella.com>
|
|
|
|
* @type {Vue}
|
|
|
|
*/
|
|
|
|
|
2020-07-31 00:30:36 -04:00
|
|
|
Vue.component('lt-node-link', {
|
2020-07-31 05:31:08 -04:00
|
|
|
template: `<a :href='getUrl()' target="_blank">{{ node }}</a>`,
|
2020-07-31 00:30:36 -04:00
|
|
|
props: ['node', 'type'],
|
2020-07-30 21:36:08 -04:00
|
|
|
data() {
|
|
|
|
return {
|
2020-07-31 00:30:36 -04:00
|
|
|
urlMap: {
|
|
|
|
0: '#',
|
|
|
|
1: 'http://stats.allstarlink.org/nodeinfo.cgi?node=',
|
|
|
|
2: 'http://www.irlp.net/status/index.php?nodeid='
|
|
|
|
}
|
2020-07-30 21:36:08 -04:00
|
|
|
}
|
|
|
|
},
|
2020-07-31 05:31:08 -04:00
|
|
|
methods: {
|
|
|
|
getUrl() {
|
|
|
|
return this.urlMap[this.type] + this.node;
|
|
|
|
}
|
2020-07-30 21:36:08 -04:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
let App = new Vue({
|
|
|
|
el: '#app',
|
|
|
|
data() {
|
|
|
|
return {
|
|
|
|
enabled: false,
|
|
|
|
intervalTimer: null,
|
|
|
|
fetchEvery: 2000,
|
|
|
|
// uri = 'http://www3.winsystem.org/monitor/ajax-logtail.php'
|
2020-07-31 00:30:36 -04:00
|
|
|
uri: 'fetchData.php',
|
2020-07-30 21:36:08 -04:00
|
|
|
lastData: null,
|
|
|
|
logs: [],
|
2020-07-31 05:31:08 -04:00
|
|
|
nodes: {},
|
2020-07-30 21:36:08 -04:00
|
|
|
nodeTypeLabels: {
|
|
|
|
0: 'Unknown',
|
|
|
|
1: 'Allstar',
|
|
|
|
2: 'IRLP'
|
|
|
|
},
|
|
|
|
nodeTypePrefixes: {
|
|
|
|
'rpt': 1,
|
|
|
|
'stn': 2
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
2020-07-31 00:30:36 -04:00
|
|
|
mounted() {
|
|
|
|
this.toggleTail();
|
|
|
|
},
|
2020-07-30 21:36:08 -04:00
|
|
|
methods: {
|
2020-07-31 00:30:36 -04:00
|
|
|
toggleTail() {
|
|
|
|
this.enabled = !this.enabled;
|
2020-07-30 21:36:08 -04:00
|
|
|
|
|
|
|
if (this.enabled) {
|
|
|
|
this.start();
|
|
|
|
} else {
|
|
|
|
this.stop();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
start() {
|
|
|
|
this.intervalTimer = setInterval(() => {
|
|
|
|
this.fetchLog();
|
|
|
|
}, this.fetchEvery);
|
|
|
|
|
|
|
|
this.fetchLog();
|
|
|
|
},
|
|
|
|
|
|
|
|
stop() {
|
|
|
|
clearInterval(this.intervalTimer);
|
|
|
|
},
|
|
|
|
|
|
|
|
fetchLog() {
|
2020-07-31 00:30:36 -04:00
|
|
|
// Force re-render component so it updates callsigns & node info
|
|
|
|
this.$forceUpdate();
|
|
|
|
|
|
|
|
axios.get(this.uri + '?cmd=log').then(({data}) => {
|
2020-07-30 21:36:08 -04:00
|
|
|
this.lastData = data;
|
|
|
|
this.parseLogData();
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
2020-07-31 21:17:47 -04:00
|
|
|
getNodeInfo(node) {
|
|
|
|
if (typeof this.nodes[node.type+node.node] !== "undefined") {
|
|
|
|
let info = this.nodes[node.type+node.node];
|
2020-07-31 00:30:36 -04:00
|
|
|
if (typeof info.callsign === "undefined") return;
|
2020-07-31 07:21:43 -04:00
|
|
|
return `${info.callsign} ${info.desc || ''} ${info.location || ''}`;
|
2020-07-31 00:30:36 -04:00
|
|
|
} else {
|
|
|
|
return '';
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2020-07-30 21:36:08 -04:00
|
|
|
parseLogData() {
|
2020-07-31 00:30:36 -04:00
|
|
|
let rows = this.lastData.split("\n");
|
2020-07-30 21:36:08 -04:00
|
|
|
|
2020-07-31 00:39:02 -04:00
|
|
|
rows.forEach((v) => {
|
2020-07-31 07:21:43 -04:00
|
|
|
// let match = v.match(/([A-Za-z]+ [0-9]+ [0-9]+\:[0-9]+\:[0-9]+) (rpt|stn)([A-Za-z0-9]+) ?.*? (?:\[(?:via) ([0-9]+))?/);
|
2020-07-31 21:17:47 -04:00
|
|
|
let match = v.match(/([A-Za-z]+ [0-9]+ [0-9]+\:[0-9]+\:[0-9]+) (rpt|stn)([A-Za-z0-9]+) (KEY|UNKEY) (?:\[(?:via) ([0-9]+)\])?(?: \[(.*)\])?/);
|
2020-07-30 21:36:08 -04:00
|
|
|
if (!match) return;
|
|
|
|
let type = this.getNodeType(match[2]);
|
2020-07-31 00:30:36 -04:00
|
|
|
|
2020-07-30 21:36:08 -04:00
|
|
|
this.addEntry(
|
|
|
|
{
|
|
|
|
node: match[3],
|
2020-07-31 22:03:21 -04:00
|
|
|
keyed: match[4] || "KEY",
|
2020-07-31 07:21:43 -04:00
|
|
|
via: match[5],
|
2020-07-30 21:36:08 -04:00
|
|
|
type: type,
|
|
|
|
typeLabel: this.getNodeTypeLabel(type),
|
2020-07-31 21:17:47 -04:00
|
|
|
// info: this.fetchNodeInfo(match[3], type),
|
|
|
|
info: typeof match[6] !== "undefined" ? match[6].trim() : undefined,
|
2020-07-31 00:30:36 -04:00
|
|
|
dateTime: moment(match[1], "MMM DD hh:mm:ss"),
|
2020-07-30 21:36:08 -04:00
|
|
|
}
|
|
|
|
);
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
|
|
|
getNodeType(type) {
|
|
|
|
return typeof this.nodeTypePrefixes[type] !== 'undefined' ? this.nodeTypePrefixes[type] : 0;
|
|
|
|
},
|
|
|
|
|
|
|
|
getNodeTypeLabel(type) {
|
|
|
|
return this.nodeTypeLabels[type];
|
|
|
|
},
|
|
|
|
|
|
|
|
fetchNodeInfo(node, type) {
|
2020-07-31 00:30:36 -04:00
|
|
|
if (type === 0) return;
|
|
|
|
|
2020-07-31 05:31:08 -04:00
|
|
|
if (this.nodes[type+node]) {
|
2020-07-31 00:30:36 -04:00
|
|
|
// Don't even call fetchNode**
|
2020-07-31 05:31:08 -04:00
|
|
|
return this.nodes[type+node];
|
2020-07-31 00:30:36 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
axios.get(this.uri + '?cmd=node&type='+type+'&node='+node).then(({data}) => {
|
2020-07-31 05:31:08 -04:00
|
|
|
this.nodes[type+node] = data;
|
2020-07-31 00:30:36 -04:00
|
|
|
});
|
2020-07-30 21:36:08 -04:00
|
|
|
},
|
|
|
|
|
|
|
|
addEntry(log) {
|
2020-07-31 00:30:36 -04:00
|
|
|
// Generate unique ID for this entry
|
|
|
|
log.uniqId = (log.node + log.dateTime.unix()).hashCode();
|
|
|
|
if (!_.findWhere(this.logs, { uniqId: log.uniqId })) {
|
|
|
|
this.logs.unshift(log);
|
|
|
|
}
|
2020-07-30 21:36:08 -04:00
|
|
|
},
|
2020-07-31 22:03:21 -04:00
|
|
|
isKeyedNow(node) {
|
|
|
|
if (node.keyed === "KEY") {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
2020-07-30 21:36:08 -04:00
|
|
|
}
|
2020-07-31 00:30:36 -04:00
|
|
|
});
|
|
|
|
|
|
|
|
String.prototype.hashCode = function() {
|
|
|
|
let hash = 0;
|
|
|
|
if (this.length === 0) {
|
|
|
|
return hash;
|
|
|
|
}
|
|
|
|
for (var i = 0; i < this.length; i++) {
|
|
|
|
let char = this.charCodeAt(i);
|
|
|
|
hash = ((hash<<5)-hash)+char;
|
|
|
|
hash = hash & hash; // Convert to 32bit integer
|
|
|
|
}
|
|
|
|
return Math.abs(hash);
|
|
|
|
};
|