From bdb8a828c2f770be329f6349add1fa09ee3db18b Mon Sep 17 00:00:00 2001 From: taraskuzyk <46264158+taraskuzyk@users.noreply.github.com> Date: Thu, 2 Nov 2023 14:45:01 -0600 Subject: [PATCH 01/11] remove unnecessary I prefix from UserFields interface --- src/lib/LoraPacket.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/lib/LoraPacket.ts b/src/lib/LoraPacket.ts index b130c35..7629b27 100644 --- a/src/lib/LoraPacket.ts +++ b/src/lib/LoraPacket.ts @@ -43,7 +43,7 @@ const MTYPE_DESCRIPTIONS = [ "Proprietary", ]; -export interface IUserFields { +export interface UserFields { CFList?: Buffer; RxDelay?: Buffer | number; DLSettings?: Buffer | number; @@ -75,7 +75,7 @@ class LoraPacket { } static fromFields( - fields: IUserFields, + fields: UserFields, AppSKey?: Buffer, NwkSKey?: Buffer, AppKey?: Buffer, @@ -190,7 +190,7 @@ class LoraPacket { } } - private _initFromFields(userFields: IUserFields): void { + private _initFromFields(userFields: UserFields): void { if (typeof userFields.MType !== "undefined") { let MTypeNo; if (typeof userFields.MType === "number") { @@ -264,7 +264,7 @@ class LoraPacket { } } - private _initialiseDataPacketFromFields(userFields: IUserFields): void { + private _initialiseDataPacketFromFields(userFields: UserFields): void { if (userFields.DevAddr && userFields.DevAddr.length == 4) { this.DevAddr = Buffer.from(userFields.DevAddr); } else { @@ -371,7 +371,7 @@ class LoraPacket { this._mergeGroupFields(); } - private _initialiseJoinRequestPacketFromFields(userFields: IUserFields): void { + private _initialiseJoinRequestPacketFromFields(userFields: UserFields): void { if (userFields.AppEUI && userFields.AppEUI.length == 8) { this.AppEUI = Buffer.from(userFields.AppEUI); } else { @@ -410,7 +410,7 @@ class LoraPacket { this._mergeGroupFields(); } - private _initialiseJoinAcceptPacketFromFields(userFields: IUserFields): void { + private _initialiseJoinAcceptPacketFromFields(userFields: UserFields): void { if (userFields.AppNonce && userFields.AppNonce.length == 3) { this.AppNonce = Buffer.from(userFields.AppNonce); } else { From ca881ff90a8b80f2b33dc0eb239940131b8d54f9 Mon Sep 17 00:00:00 2001 From: taraskuzyk <46264158+taraskuzyk@users.noreply.github.com> Date: Thu, 2 Nov 2023 15:01:51 -0600 Subject: [PATCH 02/11] fix implicit condition --- src/lib/LoraPacket.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/LoraPacket.ts b/src/lib/LoraPacket.ts index 7629b27..3ba2b17 100644 --- a/src/lib/LoraPacket.ts +++ b/src/lib/LoraPacket.ts @@ -91,7 +91,7 @@ class LoraPacket { const port = payload.getFPort(); - if (port != null && ((port === 0 && NwkSKey?.length === 16) || (port > 0 && AppSKey?.length === 16))) { + if (port !== null && ((port === 0 && NwkSKey?.length === 16) || (port > 0 && AppSKey?.length === 16))) { // crypto is reversible (just XORs FRMPayload), so we can // just do "decrypt" on the plaintext to get ciphertext From 8885f8362da52c512339dab2feb8cd00e4a80953 Mon Sep 17 00:00:00 2001 From: taraskuzyk <46264158+taraskuzyk@users.noreply.github.com> Date: Thu, 2 Nov 2023 15:05:36 -0600 Subject: [PATCH 03/11] rename constants to masks to more accurately reflect the purpose of the enum --- src/lib/LoraPacket.ts | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/lib/LoraPacket.ts b/src/lib/LoraPacket.ts index 3ba2b17..05276a3 100644 --- a/src/lib/LoraPacket.ts +++ b/src/lib/LoraPacket.ts @@ -17,7 +17,7 @@ enum LorawanVersion { V1_0 = "1.0", V1_1 = "1.1", } -enum Constants { +enum Masks { FCTRL_ADR = 0x80, FCTRL_ADRACKREQ = 0x40, FCTRL_ACK = 0x20, @@ -322,16 +322,16 @@ class LoraPacket { let fctrl = 0; if (userFields.FCtrl?.ADR) { - fctrl |= Constants.FCTRL_ADR; + fctrl |= Masks.FCTRL_ADR; } if (userFields.FCtrl?.ADRACKReq) { - fctrl |= Constants.FCTRL_ADRACKREQ; + fctrl |= Masks.FCTRL_ADRACKREQ; } if (userFields.FCtrl?.ACK) { - fctrl |= Constants.FCTRL_ACK; + fctrl |= Masks.FCTRL_ACK; } if (userFields.FCtrl?.FPending) { - fctrl |= Constants.FCTRL_FPENDING; + fctrl |= Masks.FCTRL_FPENDING; } fctrl |= this.FOpts.length & 0x0f; @@ -558,7 +558,7 @@ class LoraPacket { */ public getFCtrlACK(): boolean | null { if (!this.FCtrl) return null; - return !!(this.FCtrl.readUInt8(0) & Constants.FCTRL_ACK); + return !!(this.FCtrl.readUInt8(0) & Masks.FCTRL_ACK); } /** @@ -566,7 +566,7 @@ class LoraPacket { */ public getFCtrlADR(): boolean | null { if (!this.FCtrl) return null; - return !!(this.FCtrl.readUInt8(0) & Constants.FCTRL_ADR); + return !!(this.FCtrl.readUInt8(0) & Masks.FCTRL_ADR); } /** @@ -574,7 +574,7 @@ class LoraPacket { */ public getFCtrlADRACKReq(): boolean | null { if (!this.FCtrl) return null; - return !!(this.FCtrl.readUInt8(0) & Constants.FCTRL_ADRACKREQ); + return !!(this.FCtrl.readUInt8(0) & Masks.FCTRL_ADRACKREQ); } /** @@ -582,7 +582,7 @@ class LoraPacket { */ public getFCtrlFPending(): boolean | null { if (!this.FCtrl) return null; - return !!(this.FCtrl.readUInt8(0) & Constants.FCTRL_FPENDING); + return !!(this.FCtrl.readUInt8(0) & Masks.FCTRL_FPENDING); } /** @@ -591,7 +591,7 @@ class LoraPacket { public getDLSettingsRxOneDRoffset(): number | null { if (!this.DLSettings) return null; return ( - (this.DLSettings.readUInt8(0) & Constants.DLSETTINGS_RXONEDROFFSET_MASK) >> Constants.DLSETTINGS_RXONEDROFFSET_POS + (this.DLSettings.readUInt8(0) & Masks.DLSETTINGS_RXONEDROFFSET_MASK) >> Masks.DLSETTINGS_RXONEDROFFSET_POS ); } @@ -601,7 +601,7 @@ class LoraPacket { public getDLSettingsRxTwoDataRate(): number | null { if (!this.DLSettings) return null; return ( - (this.DLSettings.readUInt8(0) & Constants.DLSETTINGS_RXTWODATARATE_MASK) >> Constants.DLSETTINGS_RXTWODATARATE_POS + (this.DLSettings.readUInt8(0) & Masks.DLSETTINGS_RXTWODATARATE_MASK) >> Masks.DLSETTINGS_RXTWODATARATE_POS ); } @@ -610,7 +610,7 @@ class LoraPacket { */ public getDLSettingsOptNeg(): boolean | null { if (!this.DLSettings) return null; - return (this.DLSettings.readUInt8(0) & Constants.DLSETTINGS_OPTNEG_MASK) >> Constants.DLSETTINGS_OPTNEG_POS === 1; + return (this.DLSettings.readUInt8(0) & Masks.DLSETTINGS_OPTNEG_MASK) >> Masks.DLSETTINGS_OPTNEG_POS === 1; } /** @@ -618,7 +618,7 @@ class LoraPacket { */ public getRxDelayDel(): number | null { if (!this.RxDelay) return null; - return (this.RxDelay.readUInt8(0) & Constants.RXDELAY_DEL_MASK) >> Constants.RXDELAY_DEL_POS; + return (this.RxDelay.readUInt8(0) & Masks.RXDELAY_DEL_MASK) >> Masks.RXDELAY_DEL_POS; } /** From c301f54179e30e56719b6273171dfe467fb928a2 Mon Sep 17 00:00:00 2001 From: taraskuzyk <46264158+taraskuzyk@users.noreply.github.com> Date: Thu, 2 Nov 2023 15:13:49 -0600 Subject: [PATCH 04/11] rename constants to masks to more accurately reflect the purpose of the enum --- src/lib/LoraPacket.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lib/LoraPacket.ts b/src/lib/LoraPacket.ts index 05276a3..93447fc 100644 --- a/src/lib/LoraPacket.ts +++ b/src/lib/LoraPacket.ts @@ -510,14 +510,14 @@ class LoraPacket { public isDataMessage(): boolean { const mtype = this._getMType(); - if (mtype >= MType.UNCONFIRMED_DATA_UP && mtype <= MType.CONFIRMED_DATA_DOWN) return true; - return false; + return mtype >= MType.UNCONFIRMED_DATA_UP && mtype <= MType.CONFIRMED_DATA_DOWN; + } public isConfirmed(): boolean { const mtype = this._getMType(); - if (mtype === MType.CONFIRMED_DATA_DOWN || mtype === MType.CONFIRMED_DATA_UP) return true; - return false; + return mtype === MType.CONFIRMED_DATA_DOWN || mtype === MType.CONFIRMED_DATA_UP; + } /** From e39524535b1afc7cdc0b8b63a808bb3783aab458 Mon Sep 17 00:00:00 2001 From: taraskuzyk <46264158+taraskuzyk@users.noreply.github.com> Date: Fri, 3 Nov 2023 11:51:22 -0600 Subject: [PATCH 05/11] make MType Enum explicitly show the numbers, and make MType to Description consts and enums use more explicit typing --- src/lib/LoraPacket.ts | 49 +++++++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 20 deletions(-) diff --git a/src/lib/LoraPacket.ts b/src/lib/LoraPacket.ts index 93447fc..092a678 100644 --- a/src/lib/LoraPacket.ts +++ b/src/lib/LoraPacket.ts @@ -4,15 +4,34 @@ import { recalculateMIC } from "./mic"; import { Buffer } from "buffer"; enum MType { - JOIN_REQUEST, - JOIN_ACCEPT, - UNCONFIRMED_DATA_UP, - UNCONFIRMED_DATA_DOWN, - CONFIRMED_DATA_UP, - CONFIRMED_DATA_DOWN, - REJOIN_REQUEST, + JOIN_REQUEST = 0, + JOIN_ACCEPT = 1, + UNCONFIRMED_DATA_UP = 2, + UNCONFIRMED_DATA_DOWN = 3, + CONFIRMED_DATA_UP = 4, + CONFIRMED_DATA_DOWN = 5, + REJOIN_REQUEST = 6, } +const MTYPE_DESCRIPTIONS: { [key: number]: string } = { + [MType.JOIN_REQUEST]: "Join Request", + [MType.JOIN_ACCEPT]: "Join Accept", + [MType.UNCONFIRMED_DATA_UP]: "Unconfirmed Data Up", + [MType.UNCONFIRMED_DATA_DOWN]: "Unconfirmed Data Down", + [MType.CONFIRMED_DATA_UP]: "Confirmed Data Up", + [MType.CONFIRMED_DATA_DOWN]: "Confirmed Data Down", + [MType.REJOIN_REQUEST]: "Rejoin Request", +}; + + +const DESCRIPTIONS_MTYPE: { [description: string]: MType } = Object.keys(MTYPE_DESCRIPTIONS) + .reduce((acc, key) => { + const mTypeKey = key as unknown as MType; // Cast the key to MType + const description = MTYPE_DESCRIPTIONS[mTypeKey]; + acc[description] = mTypeKey; + return acc; + }, {} as { [description: string]: MType }); + enum LorawanVersion { V1_0 = "1.0", V1_1 = "1.1", @@ -32,16 +51,6 @@ enum Masks { RXDELAY_DEL_POS = 0, } -const MTYPE_DESCRIPTIONS = [ - "Join Request", - "Join Accept", - "Unconfirmed Data Up", - "Unconfirmed Data Down", - "Confirmed Data Up", - "Confirmed Data Down", - "Rejoin Request", - "Proprietary", -]; export interface UserFields { CFList?: Buffer; @@ -196,7 +205,7 @@ class LoraPacket { if (typeof userFields.MType === "number") { MTypeNo = userFields.MType; } else if (typeof userFields.MType == "string") { - const mhdr_idx = MTYPE_DESCRIPTIONS.indexOf(userFields.MType); + const mhdr_idx = DESCRIPTIONS_MTYPE[userFields.MType]; if (mhdr_idx >= 0) { MTypeNo = mhdr_idx; } else { @@ -282,7 +291,7 @@ class LoraPacket { this.MHDR = Buffer.alloc(1); this.MHDR.writeUInt8(userFields.MType << 5, 0); } else if (typeof userFields.MType === "string") { - const mhdr_idx = MTYPE_DESCRIPTIONS.indexOf(userFields.MType); + const mhdr_idx = DESCRIPTIONS_MTYPE[userFields.MType]; if (mhdr_idx >= 0) { this.MHDR = Buffer.alloc(1); this.MHDR.writeUInt8(mhdr_idx << 5, 0); @@ -524,7 +533,7 @@ class LoraPacket { * Provide MType as a string */ public getMType(): string { - return MTYPE_DESCRIPTIONS[this._getMType()]; + return MTYPE_DESCRIPTIONS[this._getMType()] || "Proprietary"; } /** From 8750c104a0187a7c2977ff3e4d14d500dfbe71bc Mon Sep 17 00:00:00 2001 From: taraskuzyk <46264158+taraskuzyk@users.noreply.github.com> Date: Fri, 3 Nov 2023 13:28:19 -0600 Subject: [PATCH 06/11] add reverseBuffer in front of more assignments for consistency --- src/lib/LoraPacket.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/LoraPacket.ts b/src/lib/LoraPacket.ts index 092a678..6698c22 100644 --- a/src/lib/LoraPacket.ts +++ b/src/lib/LoraPacket.ts @@ -158,8 +158,8 @@ class LoraPacket { this.AppNonce = reverseBuffer(incoming.slice(1, 1 + 3)); this.NetID = reverseBuffer(incoming.slice(4, 4 + 3)); this.DevAddr = reverseBuffer(incoming.slice(7, 7 + 4)); - this.DLSettings = incoming.slice(11, 11 + 1); - this.RxDelay = incoming.slice(12, 12 + 1); + this.DLSettings = reverseBuffer(incoming.slice(11, 11 + 1)); + this.RxDelay = reverseBuffer(incoming.slice(12, 12 + 1)); this.JoinReqType = Buffer.from([0xff]); if (incoming.length == 13 + 16 + 4) { From d14b0d078349fafd1cc5b9115d1d857eaf7c57a4 Mon Sep 17 00:00:00 2001 From: taraskuzyk <46264158+taraskuzyk@users.noreply.github.com> Date: Fri, 3 Nov 2023 13:47:28 -0600 Subject: [PATCH 07/11] intermediate: make all _initfromWire operations slice from the incoming packet directly for consistency --- src/lib/LoraPacket.ts | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/lib/LoraPacket.ts b/src/lib/LoraPacket.ts index 6698c22..4544b57 100644 --- a/src/lib/LoraPacket.ts +++ b/src/lib/LoraPacket.ts @@ -179,22 +179,24 @@ class LoraPacket { this.RJCount1 = reverseBuffer(incoming.slice(13, 13 + 2)); } } else if (this.isDataMessage()) { - this.FCtrl = this.MACPayload.slice(4, 5); + this.FCtrl = reverseBuffer(incoming.slice(5, 6)) + // this.FCtrl = this.MACPayload.slice(4, 5); const FCtrl = this.FCtrl.readInt8(0); const FOptsLen = FCtrl & 0x0f; - this.FOpts = this.MACPayload.slice(7, 7 + FOptsLen); + this.FOpts = incoming.slice(8, 8 + FOptsLen) + // this.FOpts = this.MACPayload.slice(7, 7 + FOptsLen); const FHDR_length = 7 + FOptsLen; - this.FHDR = this.MACPayload.slice(0, 0 + FHDR_length); - this.DevAddr = reverseBuffer(this.FHDR.slice(0, 4)); + this.FHDR = incoming.slice(1, 1 + FHDR_length); + this.DevAddr = reverseBuffer(incoming.slice(1, 5)); - this.FCnt = reverseBuffer(this.FHDR.slice(5, 7)); + this.FCnt = reverseBuffer(incoming.slice(6, 8)); if (FHDR_length == this.MACPayload.length) { this.FPort = Buffer.alloc(0); this.FRMPayload = Buffer.alloc(0); } else { - this.FPort = this.MACPayload.slice(FHDR_length, FHDR_length + 1); - this.FRMPayload = this.MACPayload.slice(FHDR_length + 1); + this.FPort = incoming.slice(FHDR_length + 1, FHDR_length + 2); + this.FRMPayload = incoming.slice(FHDR_length + 2, incoming.length - 4); } } } From d749cd06c20b5af5a49d05a2ea3b497d976f220c Mon Sep 17 00:00:00 2001 From: taraskuzyk <46264158+taraskuzyk@users.noreply.github.com> Date: Fri, 3 Nov 2023 13:54:07 -0600 Subject: [PATCH 08/11] remove commented out code --- src/lib/LoraPacket.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/lib/LoraPacket.ts b/src/lib/LoraPacket.ts index 4544b57..2ae75fc 100644 --- a/src/lib/LoraPacket.ts +++ b/src/lib/LoraPacket.ts @@ -180,11 +180,9 @@ class LoraPacket { } } else if (this.isDataMessage()) { this.FCtrl = reverseBuffer(incoming.slice(5, 6)) - // this.FCtrl = this.MACPayload.slice(4, 5); const FCtrl = this.FCtrl.readInt8(0); const FOptsLen = FCtrl & 0x0f; this.FOpts = incoming.slice(8, 8 + FOptsLen) - // this.FOpts = this.MACPayload.slice(7, 7 + FOptsLen); const FHDR_length = 7 + FOptsLen; this.FHDR = incoming.slice(1, 1 + FHDR_length); this.DevAddr = reverseBuffer(incoming.slice(1, 5)); From a581fe0607e8455d3830cfb0f877ea18570cf4c3 Mon Sep 17 00:00:00 2001 From: taraskuzyk <46264158+taraskuzyk@users.noreply.github.com> Date: Mon, 6 Nov 2023 10:44:15 -0700 Subject: [PATCH 09/11] started implementing a cleaner solution for extracting LoRaWAN fields from buffer. all tests passed, but more work needed to develop a good solution. --- src/lib/LoraPacket.ts | 88 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 71 insertions(+), 17 deletions(-) diff --git a/src/lib/LoraPacket.ts b/src/lib/LoraPacket.ts index 2ae75fc..f015274 100644 --- a/src/lib/LoraPacket.ts +++ b/src/lib/LoraPacket.ts @@ -23,7 +23,6 @@ const MTYPE_DESCRIPTIONS: { [key: number]: string } = { [MType.REJOIN_REQUEST]: "Rejoin Request", }; - const DESCRIPTIONS_MTYPE: { [description: string]: MType } = Object.keys(MTYPE_DESCRIPTIONS) .reduce((acc, key) => { const mTypeKey = key as unknown as MType; // Cast the key to MType @@ -32,6 +31,44 @@ const DESCRIPTIONS_MTYPE: { [description: string]: MType } = Object.keys(MTYPE_D return acc; }, {} as { [description: string]: MType }); +type Range = { + start: number; + end: number; +}; + +type PacketStructures = { + [key: string]: { + [key: string]: Range; + }; +}; + +const PACKET_STRUCTURES: PacketStructures = { + JOIN_REQUEST: { + AppEUI: {start: 1, end: 9}, + DevEUI: {start: 9, end: 17}, + DevNonce: {start: 17, end: 19} + }, + JOIN_ACCEPT: { + AppNonce: {start: 1, end: 4}, + NetID: {start: 4, end: 7}, + DevAddr: {start: 7, end: 11}, + DLSettings: {start: 11, end: 12}, + RxDelay: {start: 12, end: 13}, + }, + REJOIN_TYPE_1: { + NetID: {start: 2, end: 5}, + DevEUI: {start: 5, end: 13}, + RJCount0: {start: 13, end: 15} + }, + REJOIN_TYPE_2: { + JoinEUI: {start: 2, end: 10}, + DevEUI: {start: 10, end: 18}, + RJCount1: {start: 13, end: 15} + } +} + + + enum LorawanVersion { V1_0 = "1.0", V1_1 = "1.1", @@ -76,6 +113,27 @@ export interface UserFields { JoinReqType?: Buffer | number; } +function extractBytesFromBuffer(buffer: Buffer, start: number, end: number): Buffer { + return reverseBuffer(buffer.slice(start, end)); +} + +function extractStructuredBytesFromBuffer( + buffer: Buffer, name: string +): {[key: string]: Buffer} { + const structure = PACKET_STRUCTURES[name]; + let ret: {[key: string]: Buffer} = {}; + for (const key in structure) { + if (structure.hasOwnProperty(key)) { + ret[key] = extractBytesFromBuffer( + buffer, + structure[key].start, + structure[key].end + ); + } + } + return ret; +} + class LoraPacket { static fromWire(buffer: Buffer): LoraPacket { const payload = new LoraPacket(); @@ -138,6 +196,11 @@ class LoraPacket { return payload; } + private assignFromStructuredBuffer(buffer: Buffer, structure: string) { + const fields = extractStructuredBytesFromBuffer(buffer, structure) + Object.assign(this, fields) + } + private _initfromWire(contents: Buffer): void { const incoming = Buffer.from(contents); @@ -151,15 +214,9 @@ class LoraPacket { const mtype = this._getMType(); if (mtype == MType.JOIN_REQUEST) { - this.AppEUI = reverseBuffer(incoming.slice(1, 1 + 8)); - this.DevEUI = reverseBuffer(incoming.slice(9, 9 + 8)); - this.DevNonce = reverseBuffer(incoming.slice(17, 17 + 2)); + this.assignFromStructuredBuffer(incoming, "JOIN_REQUEST"); } else if (mtype == MType.JOIN_ACCEPT) { - this.AppNonce = reverseBuffer(incoming.slice(1, 1 + 3)); - this.NetID = reverseBuffer(incoming.slice(4, 4 + 3)); - this.DevAddr = reverseBuffer(incoming.slice(7, 7 + 4)); - this.DLSettings = reverseBuffer(incoming.slice(11, 11 + 1)); - this.RxDelay = reverseBuffer(incoming.slice(12, 12 + 1)); + this.assignFromStructuredBuffer(incoming, "JOIN_ACCEPT"); this.JoinReqType = Buffer.from([0xff]); if (incoming.length == 13 + 16 + 4) { @@ -170,24 +227,21 @@ class LoraPacket { } else if (mtype == MType.REJOIN_REQUEST) { this.RejoinType = incoming.slice(1, 1 + 1); if (this.RejoinType[0] === 0 || this.RejoinType[0] === 2) { - this.NetID = reverseBuffer(incoming.slice(2, 2 + 3)); - this.DevEUI = reverseBuffer(incoming.slice(5, 5 + 8)); - this.RJCount0 = reverseBuffer(incoming.slice(13, 13 + 2)); + this.assignFromStructuredBuffer(incoming, "REJOIN_TYPE_1"); } else if (this.RejoinType[0] === 1) { - this.JoinEUI = reverseBuffer(incoming.slice(2, 2 + 8)); - this.DevEUI = reverseBuffer(incoming.slice(10, 10 + 8)); - this.RJCount1 = reverseBuffer(incoming.slice(13, 13 + 2)); + this.assignFromStructuredBuffer(incoming, "REJOIN_TYPE_2"); } } else if (this.isDataMessage()) { + this.DevAddr = reverseBuffer(incoming.slice(1, 5)); this.FCtrl = reverseBuffer(incoming.slice(5, 6)) + this.FCnt = reverseBuffer(incoming.slice(6, 8)); + const FCtrl = this.FCtrl.readInt8(0); const FOptsLen = FCtrl & 0x0f; this.FOpts = incoming.slice(8, 8 + FOptsLen) const FHDR_length = 7 + FOptsLen; this.FHDR = incoming.slice(1, 1 + FHDR_length); - this.DevAddr = reverseBuffer(incoming.slice(1, 5)); - this.FCnt = reverseBuffer(incoming.slice(6, 8)); if (FHDR_length == this.MACPayload.length) { this.FPort = Buffer.alloc(0); From 0eda73def8a53c4ec55e4ad0904c0afefe68fdc5 Mon Sep 17 00:00:00 2001 From: taraskuzyk <46264158+taraskuzyk@users.noreply.github.com> Date: Wed, 15 Nov 2023 15:36:48 -0700 Subject: [PATCH 10/11] linter --- src/lib/LoraPacket.ts | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/lib/LoraPacket.ts b/src/lib/LoraPacket.ts index f015274..6509e67 100644 --- a/src/lib/LoraPacket.ts +++ b/src/lib/LoraPacket.ts @@ -1,7 +1,7 @@ -import { reverseBuffer, asHexString } from "./util"; -import { decrypt, decryptJoin, decryptFOpts } from "./crypto"; -import { recalculateMIC } from "./mic"; -import { Buffer } from "buffer"; +import {reverseBuffer, asHexString} from "./util"; +import {decrypt, decryptJoin, decryptFOpts} from "./crypto"; +import {recalculateMIC} from "./mic"; +import {Buffer} from "buffer"; enum MType { JOIN_REQUEST = 0, @@ -68,11 +68,11 @@ const PACKET_STRUCTURES: PacketStructures = { } - enum LorawanVersion { V1_0 = "1.0", V1_1 = "1.1", } + enum Masks { FCTRL_ADR = 0x80, FCTRL_ADRACKREQ = 0x40, @@ -119,9 +119,9 @@ function extractBytesFromBuffer(buffer: Buffer, start: number, end: number): Buf function extractStructuredBytesFromBuffer( buffer: Buffer, name: string -): {[key: string]: Buffer} { +): { [key: string]: Buffer } { const structure = PACKET_STRUCTURES[name]; - let ret: {[key: string]: Buffer} = {}; + let ret: { [key: string]: Buffer } = {}; for (const key in structure) { if (structure.hasOwnProperty(key)) { ret[key] = extractBytesFromBuffer( @@ -751,6 +751,7 @@ class LoraPacket { ): Buffer { return this.encryptFOpts(NwkSEncKey, NwkSKey, FCntMSBytes, ConfFCntDownTxDrTxCh); } + public encryptFOpts( NwkSEncKey: Buffer, SNwkSIntKey?: Buffer, @@ -907,4 +908,4 @@ class LoraPacket { } export default LoraPacket; -export { LorawanVersion }; +export {LorawanVersion}; From 0c415370885c03a2c4ae4321b140f4305a6b7968 Mon Sep 17 00:00:00 2001 From: Anthony Kirby Date: Mon, 20 Nov 2023 22:10:20 +0000 Subject: [PATCH 11/11] fix linter --- src/lib/LoraPacket.ts | 88 ++++++++++++++++++------------------------- 1 file changed, 36 insertions(+), 52 deletions(-) diff --git a/src/lib/LoraPacket.ts b/src/lib/LoraPacket.ts index 0ce7119..44437c5 100644 --- a/src/lib/LoraPacket.ts +++ b/src/lib/LoraPacket.ts @@ -1,7 +1,7 @@ -import {reverseBuffer, asHexString} from "./util"; -import {decrypt, decryptJoin, decryptFOpts} from "./crypto"; -import {recalculateMIC} from "./mic"; -import {Buffer} from "buffer"; +import { reverseBuffer, asHexString } from "./util"; +import { decrypt, decryptJoin, decryptFOpts } from "./crypto"; +import { recalculateMIC } from "./mic"; +import { Buffer } from "buffer"; enum MType { JOIN_REQUEST = 0, @@ -23,13 +23,12 @@ const MTYPE_DESCRIPTIONS: { [key: number]: string } = { [MType.REJOIN_REQUEST]: "Rejoin Request", }; -const DESCRIPTIONS_MTYPE: { [description: string]: MType } = Object.keys(MTYPE_DESCRIPTIONS) - .reduce((acc, key) => { - const mTypeKey = key as unknown as MType; // Cast the key to MType - const description = MTYPE_DESCRIPTIONS[mTypeKey]; - acc[description] = mTypeKey; - return acc; - }, {} as { [description: string]: MType }); +const DESCRIPTIONS_MTYPE: { [description: string]: MType } = Object.keys(MTYPE_DESCRIPTIONS).reduce((acc, key) => { + const mTypeKey = (key as unknown) as MType; // Cast the key to MType + const description = MTYPE_DESCRIPTIONS[mTypeKey]; + acc[description] = mTypeKey; + return acc; +}, {} as { [description: string]: MType }); type Range = { start: number; @@ -44,29 +43,28 @@ type PacketStructures = { const PACKET_STRUCTURES: PacketStructures = { JOIN_REQUEST: { - AppEUI: {start: 1, end: 9}, - DevEUI: {start: 9, end: 17}, - DevNonce: {start: 17, end: 19} + AppEUI: { start: 1, end: 9 }, + DevEUI: { start: 9, end: 17 }, + DevNonce: { start: 17, end: 19 }, }, JOIN_ACCEPT: { - AppNonce: {start: 1, end: 4}, - NetID: {start: 4, end: 7}, - DevAddr: {start: 7, end: 11}, - DLSettings: {start: 11, end: 12}, - RxDelay: {start: 12, end: 13}, + AppNonce: { start: 1, end: 4 }, + NetID: { start: 4, end: 7 }, + DevAddr: { start: 7, end: 11 }, + DLSettings: { start: 11, end: 12 }, + RxDelay: { start: 12, end: 13 }, }, REJOIN_TYPE_1: { - NetID: {start: 2, end: 5}, - DevEUI: {start: 5, end: 13}, - RJCount0: {start: 13, end: 15} + NetID: { start: 2, end: 5 }, + DevEUI: { start: 5, end: 13 }, + RJCount0: { start: 13, end: 15 }, }, REJOIN_TYPE_2: { - JoinEUI: {start: 2, end: 10}, - DevEUI: {start: 10, end: 18}, - RJCount1: {start: 13, end: 15} - } -} - + JoinEUI: { start: 2, end: 10 }, + DevEUI: { start: 10, end: 18 }, + RJCount1: { start: 13, end: 15 }, + }, +}; enum LorawanVersion { V1_0 = "1.0", @@ -88,7 +86,6 @@ enum Masks { RXDELAY_DEL_POS = 0, } - export interface UserFields { CFList?: Buffer; RxDelay?: Buffer | number; @@ -117,18 +114,12 @@ function extractBytesFromBuffer(buffer: Buffer, start: number, end: number): Buf return reverseBuffer(buffer.slice(start, end)); } -function extractStructuredBytesFromBuffer( - buffer: Buffer, name: string -): { [key: string]: Buffer } { +function extractStructuredBytesFromBuffer(buffer: Buffer, name: string): { [key: string]: Buffer } { const structure = PACKET_STRUCTURES[name]; - let ret: { [key: string]: Buffer } = {}; + const ret: { [key: string]: Buffer } = {}; for (const key in structure) { if (structure.hasOwnProperty(key)) { - ret[key] = extractBytesFromBuffer( - buffer, - structure[key].start, - structure[key].end - ); + ret[key] = extractBytesFromBuffer(buffer, structure[key].start, structure[key].end); } } return ret; @@ -197,8 +188,8 @@ class LoraPacket { } private assignFromStructuredBuffer(buffer: Buffer, structure: string) { - const fields = extractStructuredBytesFromBuffer(buffer, structure) - Object.assign(this, fields) + const fields = extractStructuredBytesFromBuffer(buffer, structure); + Object.assign(this, fields); } private _initfromWire(contents: Buffer): void { @@ -245,16 +236,15 @@ class LoraPacket { } } else if (this.isDataMessage()) { this.DevAddr = reverseBuffer(incoming.slice(1, 5)); - this.FCtrl = reverseBuffer(incoming.slice(5, 6)) + this.FCtrl = reverseBuffer(incoming.slice(5, 6)); this.FCnt = reverseBuffer(incoming.slice(6, 8)); const FCtrl = this.FCtrl.readInt8(0); const FOptsLen = FCtrl & 0x0f; - this.FOpts = incoming.slice(8, 8 + FOptsLen) + this.FOpts = incoming.slice(8, 8 + FOptsLen); const FHDR_length = 7 + FOptsLen; this.FHDR = incoming.slice(1, 1 + FHDR_length); - if (FHDR_length == this.MACPayload.length) { this.FPort = Buffer.alloc(0); this.FRMPayload = Buffer.alloc(0); @@ -586,13 +576,11 @@ class LoraPacket { public isDataMessage(): boolean { const mtype = this._getMType(); return mtype >= MType.UNCONFIRMED_DATA_UP && mtype <= MType.CONFIRMED_DATA_DOWN; - } public isConfirmed(): boolean { const mtype = this._getMType(); return mtype === MType.CONFIRMED_DATA_DOWN || mtype === MType.CONFIRMED_DATA_UP; - } /** @@ -665,9 +653,7 @@ class LoraPacket { */ public getDLSettingsRxOneDRoffset(): number | null { if (!this.DLSettings) return null; - return ( - (this.DLSettings.readUInt8(0) & Masks.DLSETTINGS_RXONEDROFFSET_MASK) >> Masks.DLSETTINGS_RXONEDROFFSET_POS - ); + return (this.DLSettings.readUInt8(0) & Masks.DLSETTINGS_RXONEDROFFSET_MASK) >> Masks.DLSETTINGS_RXONEDROFFSET_POS; } /** @@ -675,9 +661,7 @@ class LoraPacket { */ public getDLSettingsRxTwoDataRate(): number | null { if (!this.DLSettings) return null; - return ( - (this.DLSettings.readUInt8(0) & Masks.DLSETTINGS_RXTWODATARATE_MASK) >> Masks.DLSETTINGS_RXTWODATARATE_POS - ); + return (this.DLSettings.readUInt8(0) & Masks.DLSETTINGS_RXTWODATARATE_MASK) >> Masks.DLSETTINGS_RXTWODATARATE_POS; } /** @@ -947,4 +931,4 @@ class LoraPacket { } export default LoraPacket; -export {LorawanVersion}; +export { LorawanVersion };