diff --git a/index.html b/index.html
index 05ec84a..1af9fde 100644
--- a/index.html
+++ b/index.html
@@ -128,6 +128,15 @@
+
+
+
@@ -672,6 +681,30 @@
alert("failed to set manual add contacts");
}
},
+ async getStatsCore() {
+ try {
+ const stats = await this.connection.getStatsCore();
+ console.log(stats);
+ } catch(e) {
+ console.log(e);
+ }
+ },
+ async getStatsRadio() {
+ try {
+ const stats = await this.connection.getStatsRadio();
+ console.log(stats);
+ } catch(e) {
+ console.log(e);
+ }
+ },
+ async getStatsPackets() {
+ try {
+ const stats = await this.connection.getStatsPackets();
+ console.log(stats);
+ } catch(e) {
+ console.log(e);
+ }
+ },
showCommandLine(contact) {
// hide cli if clicked same contact
diff --git a/src/connection/connection.js b/src/connection/connection.js
index e6c008a..af6f6d6 100644
--- a/src/connection/connection.js
+++ b/src/connection/connection.js
@@ -268,6 +268,13 @@ class Connection extends EventEmitter {
await this.sendToRadioFrame(data.toBytes());
}
+ async sendCommandGetStats(statsType) {
+ const data = new BufferWriter();
+ data.writeByte(Constants.CommandCodes.GetStats);
+ data.writeByte(statsType);
+ await this.sendToRadioFrame(data.toBytes());
+ }
+
async sendCommandSendChannelData(channelIdx, pathLen, path, dataType, payload) {
const data = new BufferWriter();
data.writeByte(Constants.CommandCodes.SendChannelData);
@@ -377,6 +384,8 @@ class Connection extends EventEmitter {
this.onSignStartResponse(bufferReader);
} else if(responseCode === Constants.ResponseCodes.Signature){
this.onSignatureResponse(bufferReader);
+ } else if(responseCode === Constants.ResponseCodes.Stats){
+ this.onStatsResponse(bufferReader);
} else if(responseCode === Constants.ResponseCodes.ChannelDataRecv){
this.onChannelDataRecvResponse(bufferReader);
} else if(responseCode === Constants.PushCodes.Advert){
@@ -625,6 +634,47 @@ class Connection extends EventEmitter {
});
}
+ onStatsResponse(bufferReader) {
+
+ const type = bufferReader.readUInt8();
+ const raw = bufferReader.readRemainingBytes();
+ const rawBufferReader = new BufferReader(raw);
+
+ var data = {};
+ if(type === Constants.StatsTypes.Core){
+ data = {
+ batteryMilliVolts: rawBufferReader.readUInt16LE(),
+ uptimeSecs: rawBufferReader.readUInt32LE(),
+ queueLen: rawBufferReader.readUInt8(),
+ };
+ } else if(type === Constants.StatsTypes.Radio){
+ data = {
+ noiseFloor: rawBufferReader.readInt16LE(),
+ lastRssi: rawBufferReader.readInt8(),
+ lastSnr: rawBufferReader.readInt8() / 4,
+ txAirSecs: rawBufferReader.readUInt32LE(),
+ rxAirSecs: rawBufferReader.readUInt32LE(),
+ };
+ } else if(type === Constants.StatsTypes.Packets){
+ data = {
+ recv: rawBufferReader.readUInt32LE(),
+ sent: rawBufferReader.readUInt32LE(),
+ nSentFlood: rawBufferReader.readUInt32LE(),
+ nSentDirect: rawBufferReader.readUInt32LE(),
+ nRecvFlood: rawBufferReader.readUInt32LE(),
+ nRecvDirect: rawBufferReader.readUInt32LE(),
+ nRecvErrors: rawBufferReader.getRemainingBytesCount() >= 4 ? rawBufferReader.readUInt32LE() : null,
+ };
+ }
+
+ this.emit(Constants.ResponseCodes.Stats, {
+ type: type,
+ raw: raw,
+ data: data,
+ });
+
+ }
+
onChannelDataRecvResponse(bufferReader) {
const snr = bufferReader.readInt8() / 4;
const reserved1 = bufferReader.readByte();
@@ -1856,6 +1906,56 @@ class Connection extends EventEmitter {
});
}
+ getStats(statsType) {
+ return new Promise(async (resolve, reject) => {
+ try {
+
+ // resolve promise when we receive stats
+ const onStats = (response) => {
+
+ // make sure stats response is for this stats request
+ if(response.type !== statsType){
+ return;
+ }
+
+ this.off(Constants.ResponseCodes.Stats, onStats);
+ this.off(Constants.ResponseCodes.Err, onErr);
+ resolve(response);
+
+ }
+
+ // reject promise when we receive err
+ const onErr = () => {
+ this.off(Constants.ResponseCodes.Stats, onStats);
+ this.off(Constants.ResponseCodes.Err, onErr);
+ reject();
+ }
+
+ // listen for events
+ this.once(Constants.ResponseCodes.Stats, onStats);
+ this.once(Constants.ResponseCodes.Err, onErr);
+
+ // send get stats
+ await this.sendCommandGetStats(statsType);
+
+ } catch(e) {
+ reject(e);
+ }
+ });
+ }
+
+ getStatsCore() {
+ return this.getStats(Constants.StatsTypes.Core);
+ }
+
+ getStatsRadio() {
+ return this.getStats(Constants.StatsTypes.Radio);
+ }
+
+ getStatsPackets() {
+ return this.getStats(Constants.StatsTypes.Packets);
+ }
+
sendChannelData(channelIdx, pathLen, path, dataType, payload) {
return new Promise(async (resolve, reject) => {
try {
diff --git a/src/constants.js b/src/constants.js
index c4c4236..4ba7e78 100644
--- a/src/constants.js
+++ b/src/constants.js
@@ -17,6 +17,12 @@ class Constants {
Dev: 0xFFFF, // developer namespace for experimenting with group/channel datagrams and building apps
}
+ static StatsTypes = {
+ Core: 0,
+ Radio: 1,
+ Packets: 2,
+ }
+
static CommandCodes = {
AppStart: 1,
SendTxtMsg: 2,
@@ -59,6 +65,8 @@ class Constants {
SetFloodScope: 54,
+ GetStats: 56,
+
SendChannelData: 62,
}
@@ -82,6 +90,7 @@ class Constants {
ChannelInfo: 18,
SignStart: 19,
Signature: 20,
+ Stats: 24,
ChannelDataRecv: 27,
}