meshtastic/src/components/tools/FrequencyCalculator.tsx

406 lines
8.5 KiB
TypeScript
Raw Normal View History

2023-12-26 04:17:57 -08:00
import { Protobuf, Types } from "@meshtastic/js";
import React, { useEffect, useState } from "react";
2023-05-12 04:40:11 -07:00
interface Region {
2024-02-08 13:23:54 -08:00
freqStart: number;
freqEnd: number;
dutyCycle: number;
2023-09-09 05:16:14 -07:00
spacing: number;
2024-02-08 13:23:54 -08:00
powerLimit: number;
2023-05-12 04:40:11 -07:00
}
interface Modem {
2023-09-09 05:16:14 -07:00
bw: number;
cr: number;
sf: number;
2023-05-12 04:40:11 -07:00
}
2024-01-05 17:02:32 -08:00
const RegionData = new Map<
Protobuf.Config.Config_LoRaConfig_RegionCode,
Region
>([
2023-09-09 05:16:14 -07:00
[
2024-01-05 17:02:32 -08:00
Protobuf.Config.Config_LoRaConfig_RegionCode.US,
2023-09-09 05:16:14 -07:00
{
2024-02-08 13:23:54 -08:00
freqStart: 902.0,
freqEnd: 928.0,
dutyCycle: 100,
2023-09-09 05:16:14 -07:00
spacing: 0,
2024-02-08 13:23:54 -08:00
powerLimit: 30,
2023-09-09 05:16:14 -07:00
},
],
[
2024-01-05 17:02:32 -08:00
Protobuf.Config.Config_LoRaConfig_RegionCode.EU_433,
2023-09-09 05:16:14 -07:00
{
2024-02-08 13:23:54 -08:00
freqStart: 433.0,
freqEnd: 434.0,
dutyCycle: 10,
2023-09-09 05:16:14 -07:00
spacing: 0,
2024-02-08 13:23:54 -08:00
powerLimit: 12,
2023-09-09 05:16:14 -07:00
},
],
[
2024-01-05 17:02:32 -08:00
Protobuf.Config.Config_LoRaConfig_RegionCode.EU_868,
2023-09-09 05:16:14 -07:00
{
2024-02-08 13:23:54 -08:00
freqStart: 869.4,
freqEnd: 869.65,
dutyCycle: 10,
2023-09-09 05:16:14 -07:00
spacing: 0,
2024-02-08 13:23:54 -08:00
powerLimit: 27,
2023-09-09 05:16:14 -07:00
},
],
[
2024-01-05 17:02:32 -08:00
Protobuf.Config.Config_LoRaConfig_RegionCode.CN,
2023-09-09 05:16:14 -07:00
{
2024-02-08 13:23:54 -08:00
freqStart: 470.0,
freqEnd: 510.0,
dutyCycle: 100,
2023-09-09 05:16:14 -07:00
spacing: 0,
2024-02-08 13:23:54 -08:00
powerLimit: 19,
2023-09-09 05:16:14 -07:00
},
],
[
2024-01-05 17:02:32 -08:00
Protobuf.Config.Config_LoRaConfig_RegionCode.JP,
2023-09-09 05:16:14 -07:00
{
2024-02-08 13:23:54 -08:00
freqStart: 920.8,
freqEnd: 927.8,
dutyCycle: 100,
2023-09-09 05:16:14 -07:00
spacing: 0,
2024-02-08 13:23:54 -08:00
powerLimit: 16,
2023-09-09 05:16:14 -07:00
},
],
[
2024-01-05 17:02:32 -08:00
Protobuf.Config.Config_LoRaConfig_RegionCode.ANZ,
2023-09-09 05:16:14 -07:00
{
2024-02-08 13:23:54 -08:00
freqStart: 915.0,
freqEnd: 928.0,
dutyCycle: 100,
2023-09-09 05:16:14 -07:00
spacing: 0,
2024-02-08 13:23:54 -08:00
powerLimit: 30,
2023-09-09 05:16:14 -07:00
},
],
[
2024-01-05 17:02:32 -08:00
Protobuf.Config.Config_LoRaConfig_RegionCode.RU,
2023-09-09 05:16:14 -07:00
{
2024-02-08 13:23:54 -08:00
freqStart: 868.7,
freqEnd: 869.2,
dutyCycle: 100,
2023-09-09 05:16:14 -07:00
spacing: 0,
2024-02-08 13:23:54 -08:00
powerLimit: 20,
2023-09-09 05:16:14 -07:00
},
],
[
2024-01-05 17:02:32 -08:00
Protobuf.Config.Config_LoRaConfig_RegionCode.KR,
2023-09-09 05:16:14 -07:00
{
2024-02-08 13:23:54 -08:00
freqStart: 920.0,
freqEnd: 923.0,
dutyCycle: 100,
2023-09-09 05:16:14 -07:00
spacing: 0,
2024-02-08 13:23:54 -08:00
powerLimit: 0,
2023-09-09 05:16:14 -07:00
},
],
[
2024-01-05 17:02:32 -08:00
Protobuf.Config.Config_LoRaConfig_RegionCode.TW,
2023-09-09 05:16:14 -07:00
{
2024-02-08 13:23:54 -08:00
freqStart: 920.0,
freqEnd: 925.0,
dutyCycle: 100,
2023-09-09 05:16:14 -07:00
spacing: 0,
2024-02-08 13:23:54 -08:00
powerLimit: 0,
2023-09-09 05:16:14 -07:00
},
],
[
2024-01-05 17:02:32 -08:00
Protobuf.Config.Config_LoRaConfig_RegionCode.IN,
2023-09-09 05:16:14 -07:00
{
2024-02-08 13:23:54 -08:00
freqStart: 865.0,
freqEnd: 867.0,
dutyCycle: 100,
2023-09-09 05:16:14 -07:00
spacing: 0,
2024-02-08 13:23:54 -08:00
powerLimit: 30,
2023-09-09 05:16:14 -07:00
},
],
[
2024-01-05 17:02:32 -08:00
Protobuf.Config.Config_LoRaConfig_RegionCode.NZ_865,
2023-09-09 05:16:14 -07:00
{
2024-02-08 13:23:54 -08:00
freqStart: 864.0,
freqEnd: 868.0,
dutyCycle: 100,
2023-09-09 05:16:14 -07:00
spacing: 0,
2024-02-08 13:23:54 -08:00
powerLimit: 36,
2023-09-09 05:16:14 -07:00
},
],
[
2024-01-05 17:02:32 -08:00
Protobuf.Config.Config_LoRaConfig_RegionCode.TH,
2023-09-09 05:16:14 -07:00
{
2024-02-08 13:23:54 -08:00
freqStart: 920.0,
freqEnd: 925.0,
dutyCycle: 100,
2023-09-09 05:16:14 -07:00
spacing: 0,
2024-02-08 13:23:54 -08:00
powerLimit: 16,
2023-09-09 05:16:14 -07:00
},
],
[
2024-01-05 17:02:32 -08:00
Protobuf.Config.Config_LoRaConfig_RegionCode.UA_433,
2023-09-09 05:16:14 -07:00
{
2024-02-08 13:23:54 -08:00
freqStart: 433.0,
freqEnd: 434.7,
dutyCycle: 10,
2023-09-09 05:16:14 -07:00
spacing: 0,
2024-02-08 13:23:54 -08:00
powerLimit: 10,
2023-09-09 05:16:14 -07:00
},
],
[
2024-01-05 17:02:32 -08:00
Protobuf.Config.Config_LoRaConfig_RegionCode.UA_868,
2023-09-09 05:16:14 -07:00
{
2024-02-08 13:23:54 -08:00
freqStart: 868.0,
freqEnd: 868.6,
dutyCycle: 1,
2023-09-09 05:16:14 -07:00
spacing: 0,
2024-02-08 13:23:54 -08:00
powerLimit: 14,
2023-09-09 05:16:14 -07:00
},
],
2024-01-15 22:36:17 -08:00
[
Protobuf.Config.Config_LoRaConfig_RegionCode.MY_433,
{
2024-02-08 13:23:54 -08:00
freqStart: 433.0,
freqEnd: 435.0,
dutyCycle: 100,
2024-01-15 22:36:17 -08:00
spacing: 0,
2024-02-08 13:23:54 -08:00
powerLimit: 20,
2024-01-15 22:36:17 -08:00
},
],
[
Protobuf.Config.Config_LoRaConfig_RegionCode.MY_919,
{
2024-02-08 13:23:54 -08:00
freqStart: 919.0,
freqEnd: 924.0,
dutyCycle: 100,
2024-01-15 22:36:17 -08:00
spacing: 0,
2024-02-08 13:23:54 -08:00
powerLimit: 27,
2024-01-15 22:36:17 -08:00
},
],
2024-02-12 22:24:32 -08:00
[
Protobuf.Config.Config_LoRaConfig_RegionCode.SG_923,
{
2024-07-22 16:56:09 -07:00
freqStart: 917.0,
freqEnd: 925.0,
dutyCycle: 100,
2024-02-12 22:24:32 -08:00
spacing: 0,
2024-07-22 16:56:09 -07:00
powerLimit: 20,
2024-02-12 22:24:32 -08:00
},
],
2023-09-09 05:16:14 -07:00
[
2024-01-05 17:02:32 -08:00
Protobuf.Config.Config_LoRaConfig_RegionCode.LORA_24,
2023-09-09 05:16:14 -07:00
{
2024-02-08 13:23:54 -08:00
freqStart: 2400.0,
freqEnd: 2483.5,
dutyCycle: 100,
2023-09-09 05:16:14 -07:00
spacing: 0,
2024-02-08 13:23:54 -08:00
powerLimit: 10,
2023-09-09 05:16:14 -07:00
},
],
[
2024-01-05 17:02:32 -08:00
Protobuf.Config.Config_LoRaConfig_RegionCode.UNSET,
2023-09-09 05:16:14 -07:00
{
2024-02-08 13:23:54 -08:00
freqStart: 902.0,
freqEnd: 928.0,
dutyCycle: 100,
2023-09-09 05:16:14 -07:00
spacing: 0,
2024-02-08 13:23:54 -08:00
powerLimit: 30,
2023-09-09 05:16:14 -07:00
},
],
2023-05-12 04:40:11 -07:00
]);
2024-01-05 17:02:32 -08:00
const modemPresets = new Map<
Protobuf.Config.Config_LoRaConfig_ModemPreset,
Modem
>([
[
Protobuf.Config.Config_LoRaConfig_ModemPreset.SHORT_TURBO,
{
bw: 500,
cr: 5,
sf: 7,
},
],
2023-09-09 05:16:14 -07:00
[
2024-01-05 17:02:32 -08:00
Protobuf.Config.Config_LoRaConfig_ModemPreset.SHORT_FAST,
2023-09-09 05:16:14 -07:00
{
bw: 250,
cr: 8,
sf: 7,
},
],
[
2024-01-05 17:02:32 -08:00
Protobuf.Config.Config_LoRaConfig_ModemPreset.SHORT_SLOW,
2023-09-09 05:16:14 -07:00
{
bw: 250,
cr: 8,
sf: 8,
},
],
[
2024-01-05 17:02:32 -08:00
Protobuf.Config.Config_LoRaConfig_ModemPreset.MEDIUM_FAST,
2023-09-09 05:16:14 -07:00
{
bw: 250,
cr: 8,
sf: 9,
},
],
[
2024-01-05 17:02:32 -08:00
Protobuf.Config.Config_LoRaConfig_ModemPreset.MEDIUM_SLOW,
2023-09-09 05:16:14 -07:00
{
bw: 250,
cr: 8,
sf: 10,
},
],
[
2024-01-05 17:02:32 -08:00
Protobuf.Config.Config_LoRaConfig_ModemPreset.LONG_FAST,
2023-09-09 05:16:14 -07:00
{
bw: 250,
cr: 8,
sf: 11,
},
],
[
2024-01-05 17:02:32 -08:00
Protobuf.Config.Config_LoRaConfig_ModemPreset.LONG_MODERATE,
2023-09-09 05:16:14 -07:00
{
bw: 125,
cr: 8,
sf: 11,
},
],
[
2024-01-05 17:02:32 -08:00
Protobuf.Config.Config_LoRaConfig_ModemPreset.LONG_SLOW,
2023-09-09 05:16:14 -07:00
{
bw: 125,
cr: 8,
sf: 12,
},
],
[
2024-01-05 17:02:32 -08:00
Protobuf.Config.Config_LoRaConfig_ModemPreset.VERY_LONG_SLOW,
2023-09-09 05:16:14 -07:00
{
bw: 62.5,
cr: 8,
sf: 12,
},
],
2023-05-12 04:40:11 -07:00
]);
export const FrequencyCalculator = (): JSX.Element => {
2023-09-09 05:16:14 -07:00
const [modemPreset, setModemPreset] =
useState<Protobuf.Config.Config_LoRaConfig_ModemPreset>(
2024-01-05 17:02:32 -08:00
Protobuf.Config.Config_LoRaConfig_ModemPreset.LONG_FAST,
2023-09-09 05:16:14 -07:00
);
const [region, setRegion] =
useState<Protobuf.Config.Config_LoRaConfig_RegionCode>(
2024-01-05 17:02:32 -08:00
Protobuf.Config.Config_LoRaConfig_RegionCode.US,
2023-09-09 05:16:14 -07:00
);
const [channel, setChannel] = useState<Types.ChannelNumber>(
Types.ChannelNumber.Primary,
2023-09-09 05:16:14 -07:00
);
const [numChannels, setNumChannels] = useState<number>(0);
const [channelFrequency, setChannelFrequency] = useState<number>(0);
2023-05-12 04:40:11 -07:00
2023-09-09 05:16:14 -07:00
useEffect(() => {
const selectedRegion = RegionData.get(region);
const selectedModemPreset = modemPresets.get(modemPreset);
const calculatedNumChannels = Math.floor(
2024-02-08 13:23:54 -08:00
(selectedRegion.freqEnd - selectedRegion.freqStart) /
2023-09-09 05:16:14 -07:00
(selectedRegion.spacing + selectedModemPreset.bw / 1000),
);
2023-09-09 05:16:14 -07:00
setNumChannels(calculatedNumChannels);
2023-09-09 05:16:14 -07:00
let updatedChannel = channel;
if (updatedChannel >= calculatedNumChannels) {
updatedChannel = 0;
}
2023-09-09 05:16:14 -07:00
setChannel(updatedChannel);
2023-09-09 05:16:14 -07:00
setChannelFrequency(
2024-02-08 13:23:54 -08:00
selectedRegion.freqStart +
2023-09-09 05:16:14 -07:00
selectedModemPreset.bw / 2000 +
updatedChannel * (selectedModemPreset.bw / 1000),
);
}, [modemPreset, region, channel]);
2023-05-12 04:40:11 -07:00
2023-09-09 05:16:14 -07:00
return (
<div className="flex flex-col border-l-[5px] shadow-md my-4 border-accent rounded-lg p-4 bg-secondary gap-2">
<div className="flex gap-2">
<label htmlFor="modemPreset">Modem Preset:</label>
2023-09-09 05:16:14 -07:00
<select
id="modemPreset"
2023-09-09 05:16:14 -07:00
value={modemPreset}
onChange={(e) =>
setModemPreset(
2024-02-08 13:23:54 -08:00
Number.parseInt(
2023-09-09 05:16:14 -07:00
e.target.value,
2024-01-05 17:02:32 -08:00
) as Protobuf.Config.Config_LoRaConfig_ModemPreset,
2023-09-09 05:16:14 -07:00
)
}
>
{Array.from(modemPresets.keys()).map((key) => (
<option key={key} value={key}>
2024-01-05 17:02:32 -08:00
{Protobuf.Config.Config_LoRaConfig_ModemPreset[key]}
2023-09-09 05:16:14 -07:00
</option>
))}
</select>
</div>
<div className="flex gap-2">
<label htmlFor="region">Region:</label>
2023-09-09 05:16:14 -07:00
<select
id="region"
2023-09-09 05:16:14 -07:00
value={region}
2024-02-08 13:23:54 -08:00
onChange={(e) => setRegion(Number.parseInt(e.target.value))}
2023-09-09 05:16:14 -07:00
>
{Array.from(RegionData.keys()).map((key) => (
<option key={key} value={key}>
2024-01-05 17:02:32 -08:00
{Protobuf.Config.Config_LoRaConfig_RegionCode[key]}
2023-09-09 05:16:14 -07:00
</option>
))}
</select>
</div>
<div className="flex gap-2 mb-4">
<label htmlFor="numSlots" className="font-semibold">
Number of slots:
</label>
<input
id="numSlots"
type="number"
disabled={true}
value={numChannels}
/>
</div>
2023-09-09 05:16:14 -07:00
<div className="flex gap-2">
<label htmlFor="frequencySlot">Frequency Slot:</label>
2023-09-09 05:16:14 -07:00
<select
id="frequencySlot"
2023-09-09 05:16:14 -07:00
value={channel}
2024-02-08 13:23:54 -08:00
onChange={(e) => setChannel(Number.parseInt(e.target.value))}
2023-09-09 05:16:14 -07:00
>
{Array.from(Array(numChannels).keys()).map((key) => (
<option key={key} value={key}>
{key + 1}
</option>
))}
</select>
</div>
<div className="flex gap-2">
<label htmlFor="slotFrequency" className="font-semibold">
Frequency of slot:
</label>
<input
id="slotFrequency"
type="number"
disabled={true}
value={channelFrequency}
/>
2023-09-09 05:16:14 -07:00
</div>
</div>
);
2023-05-12 04:40:11 -07:00
};