device store cleanup & peers page improvements
This commit is contained in:
+2
-1
@@ -27,7 +27,7 @@
|
|||||||
"@heroicons/react": "^2.0.13",
|
"@heroicons/react": "^2.0.13",
|
||||||
"@hookform/error-message": "^2.0.1",
|
"@hookform/error-message": "^2.0.1",
|
||||||
"@hookform/resolvers": "^2.9.10",
|
"@hookform/resolvers": "^2.9.10",
|
||||||
"@meshtastic/meshtasticjs": "^0.9.2",
|
"@meshtastic/meshtasticjs": "^0.9.7",
|
||||||
"@tailwindcss/line-clamp": "^0.4.2",
|
"@tailwindcss/line-clamp": "^0.4.2",
|
||||||
"@tailwindcss/typography": "^0.5.8",
|
"@tailwindcss/typography": "^0.5.8",
|
||||||
"@turf/turf": "^6.5.0",
|
"@turf/turf": "^6.5.0",
|
||||||
@@ -52,6 +52,7 @@
|
|||||||
"react-map-gl": "^7.0.20",
|
"react-map-gl": "^7.0.20",
|
||||||
"react-qrcode-logo": "^2.8.0",
|
"react-qrcode-logo": "^2.8.0",
|
||||||
"rfc4648": "^1.5.2",
|
"rfc4648": "^1.5.2",
|
||||||
|
"timeago-react": "^3.0.5",
|
||||||
"zustand": "4.1.5"
|
"zustand": "4.1.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
Generated
+19
-4
@@ -6,7 +6,7 @@ specifiers:
|
|||||||
'@heroicons/react': ^2.0.13
|
'@heroicons/react': ^2.0.13
|
||||||
'@hookform/error-message': ^2.0.1
|
'@hookform/error-message': ^2.0.1
|
||||||
'@hookform/resolvers': ^2.9.10
|
'@hookform/resolvers': ^2.9.10
|
||||||
'@meshtastic/meshtasticjs': ^0.9.2
|
'@meshtastic/meshtasticjs': ^0.9.7
|
||||||
'@tailwindcss/forms': ^0.5.3
|
'@tailwindcss/forms': ^0.5.3
|
||||||
'@tailwindcss/line-clamp': ^0.4.2
|
'@tailwindcss/line-clamp': ^0.4.2
|
||||||
'@tailwindcss/typography': ^0.5.8
|
'@tailwindcss/typography': ^0.5.8
|
||||||
@@ -56,6 +56,7 @@ specifiers:
|
|||||||
rollup-plugin-visualizer: ^5.9.0
|
rollup-plugin-visualizer: ^5.9.0
|
||||||
tailwindcss: ^3.2.4
|
tailwindcss: ^3.2.4
|
||||||
tar: ^6.1.13
|
tar: ^6.1.13
|
||||||
|
timeago-react: ^3.0.5
|
||||||
tslib: ^2.4.1
|
tslib: ^2.4.1
|
||||||
typescript: ^4.9.4
|
typescript: ^4.9.4
|
||||||
unimported: ^1.24.0
|
unimported: ^1.24.0
|
||||||
@@ -70,7 +71,7 @@ dependencies:
|
|||||||
'@heroicons/react': 2.0.13_react@18.2.0
|
'@heroicons/react': 2.0.13_react@18.2.0
|
||||||
'@hookform/error-message': 2.0.1_7yhncxxycytkes3mwygyjxyp6u
|
'@hookform/error-message': 2.0.1_7yhncxxycytkes3mwygyjxyp6u
|
||||||
'@hookform/resolvers': 2.9.10_react-hook-form@7.41.3
|
'@hookform/resolvers': 2.9.10_react-hook-form@7.41.3
|
||||||
'@meshtastic/meshtasticjs': 0.9.2
|
'@meshtastic/meshtasticjs': 0.9.7
|
||||||
'@tailwindcss/line-clamp': 0.4.2_tailwindcss@3.2.4
|
'@tailwindcss/line-clamp': 0.4.2_tailwindcss@3.2.4
|
||||||
'@tailwindcss/typography': 0.5.8_tailwindcss@3.2.4
|
'@tailwindcss/typography': 0.5.8_tailwindcss@3.2.4
|
||||||
'@turf/turf': 6.5.0
|
'@turf/turf': 6.5.0
|
||||||
@@ -95,6 +96,7 @@ dependencies:
|
|||||||
react-map-gl: 7.0.20_6eczaga5xxiwzxtfiyk6fioasq
|
react-map-gl: 7.0.20_6eczaga5xxiwzxtfiyk6fioasq
|
||||||
react-qrcode-logo: 2.8.0_biqbaboplfbrettd7655fr4n2y
|
react-qrcode-logo: 2.8.0_biqbaboplfbrettd7655fr4n2y
|
||||||
rfc4648: 1.5.2
|
rfc4648: 1.5.2
|
||||||
|
timeago-react: 3.0.5_react@18.2.0
|
||||||
zustand: 4.1.5_immer@9.0.16+react@18.2.0
|
zustand: 4.1.5_immer@9.0.16+react@18.2.0
|
||||||
|
|
||||||
devDependencies:
|
devDependencies:
|
||||||
@@ -1710,8 +1712,8 @@ packages:
|
|||||||
engines: {node: '>=6.0.0'}
|
engines: {node: '>=6.0.0'}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@meshtastic/meshtasticjs/0.9.2:
|
/@meshtastic/meshtasticjs/0.9.7:
|
||||||
resolution: {integrity: sha512-rS/dK3RekRC9R930/RbNgdcktQ/XZv/bPpFZ6/6PJ61+8NjguN6SeNE3GP007TS5GSkp0zu3IgfOHn+pEL94KA==}
|
resolution: {integrity: sha512-FQAfgJ2FeC55HbmOR1Z7Y3iIyXN32YO5OmtsviPolaZWivE7cCCfwSQGOHrtQUwXUSRv6Up0ucJ0eW7teaXxhA==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@protobuf-ts/runtime': 2.8.2
|
'@protobuf-ts/runtime': 2.8.2
|
||||||
glob: 8.0.3
|
glob: 8.0.3
|
||||||
@@ -6430,6 +6432,19 @@ packages:
|
|||||||
readable-stream: 3.6.0
|
readable-stream: 3.6.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/timeago-react/3.0.5_react@18.2.0:
|
||||||
|
resolution: {integrity: sha512-1k/aDt+ADpcABCmg3BIBuZSa7aSxolmuYFkdcpL7mlNkFcDAK/KwuxLf68gowhM7Oq3vWTE7LPeq3kLkSt45Jg==}
|
||||||
|
peerDependencies:
|
||||||
|
react: ^0.14.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0
|
||||||
|
dependencies:
|
||||||
|
react: 18.2.0
|
||||||
|
timeago.js: 4.0.2
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/timeago.js/4.0.2:
|
||||||
|
resolution: {integrity: sha512-a7wPxPdVlQL7lqvitHGGRsofhdwtkoSXPGATFuSOA2i1ZNQEPLrGnj68vOp2sOJTCFAQVXPeNMX/GctBaO9L2w==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/tiny-glob/0.2.9:
|
/tiny-glob/0.2.9:
|
||||||
resolution: {integrity: sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==}
|
resolution: {integrity: sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==}
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|||||||
@@ -52,8 +52,6 @@ export const Network = (): JSX.Element => {
|
|||||||
}, [reset, config.network]);
|
}, [reset, config.network]);
|
||||||
|
|
||||||
const onSubmit = handleSubmit((data) => {
|
const onSubmit = handleSubmit((data) => {
|
||||||
console.log(data);
|
|
||||||
|
|
||||||
if (connection) {
|
if (connection) {
|
||||||
void toast.promise(
|
void toast.promise(
|
||||||
connection
|
connection
|
||||||
|
|||||||
@@ -22,12 +22,9 @@ export const ChannelChat = ({ channel }: ChannelChatProps): JSX.Element => {
|
|||||||
lastMsgSameUser={
|
lastMsgSameUser={
|
||||||
index === 0
|
index === 0
|
||||||
? false
|
? false
|
||||||
: channel.messages[index - 1].packet.from ===
|
: channel.messages[index - 1].from === message.from
|
||||||
message.packet.from
|
|
||||||
}
|
|
||||||
sender={
|
|
||||||
nodes.find((node) => node.data.num === message.packet.from)?.data
|
|
||||||
}
|
}
|
||||||
|
sender={nodes.find((node) => node.data.num === message.from)?.data}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -25,12 +25,12 @@ export const Message = ({
|
|||||||
const { setPeerInfoOpen, setActivePeer, connection } = useDevice();
|
const { setPeerInfoOpen, setActivePeer, connection } = useDevice();
|
||||||
|
|
||||||
const openPeer = (): void => {
|
const openPeer = (): void => {
|
||||||
setActivePeer(message.packet.from);
|
setActivePeer(message.from);
|
||||||
setPeerInfoOpen(true);
|
setPeerInfoOpen(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
return lastMsgSameUser ? (
|
return lastMsgSameUser ? (
|
||||||
<div className="ml-4 flex">
|
<div className="ml-5 flex">
|
||||||
{message.state === "ack" ? (
|
{message.state === "ack" ? (
|
||||||
<CheckCircleIcon className="my-auto h-4 text-textSecondary" />
|
<CheckCircleIcon className="my-auto h-4 text-textSecondary" />
|
||||||
) : message.state === "waiting" ? (
|
) : message.state === "waiting" ? (
|
||||||
@@ -46,7 +46,7 @@ export const Message = ({
|
|||||||
message.state === "ack" ? "text-textPrimary" : "text-textSecondary"
|
message.state === "ack" ? "text-textPrimary" : "text-textSecondary"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{message.text}
|
{message.data}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@@ -63,14 +63,13 @@ export const Message = ({
|
|||||||
{sender?.user?.longName ?? "UNK"}
|
{sender?.user?.longName ?? "UNK"}
|
||||||
</span>
|
</span>
|
||||||
<span className="mt-1 font-mono text-xs text-textSecondary">
|
<span className="mt-1 font-mono text-xs text-textSecondary">
|
||||||
{new Date(message.packet.rxTime).toLocaleTimeString(undefined, {
|
{message.rxTime.toLocaleTimeString(undefined, {
|
||||||
hour: "2-digit",
|
hour: "2-digit",
|
||||||
minute: "2-digit"
|
minute: "2-digit"
|
||||||
})}
|
})}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex">
|
<div className="ml-1 flex">
|
||||||
{/* <ExclamationCircleIcon /> */}
|
|
||||||
{message.state === "ack" ? (
|
{message.state === "ack" ? (
|
||||||
<CheckCircleIcon className="my-auto h-4 text-textSecondary" />
|
<CheckCircleIcon className="my-auto h-4 text-textSecondary" />
|
||||||
) : message.state === "waiting" ? (
|
) : message.state === "waiting" ? (
|
||||||
@@ -88,7 +87,7 @@ export const Message = ({
|
|||||||
: "text-textSecondary"
|
: "text-textSecondary"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{message.text}
|
{message.data}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+84
-120
@@ -15,12 +15,12 @@ export type Page =
|
|||||||
| "info"
|
| "info"
|
||||||
| "logs";
|
| "logs";
|
||||||
|
|
||||||
export interface MessageWithState extends Types.MessagePacket {
|
export interface MessageWithState extends Types.PacketMetadata<string> {
|
||||||
state: MessageState;
|
state: MessageState;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface WaypointIDWithState
|
export interface WaypointIDWithState
|
||||||
extends Omit<Types.WaypointPacket, "data"> {
|
extends Omit<Types.PacketMetadata<Protobuf.Waypoint>, "data"> {
|
||||||
waypointID: number;
|
waypointID: number;
|
||||||
state: MessageState;
|
state: MessageState;
|
||||||
}
|
}
|
||||||
@@ -42,6 +42,12 @@ export interface Node {
|
|||||||
data: Protobuf.NodeInfo;
|
data: Protobuf.NodeInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface processPacketParams {
|
||||||
|
from: number;
|
||||||
|
snr: number;
|
||||||
|
time: number;
|
||||||
|
}
|
||||||
|
|
||||||
export interface Device {
|
export interface Device {
|
||||||
id: number;
|
id: number;
|
||||||
ready: boolean;
|
ready: boolean;
|
||||||
@@ -69,20 +75,22 @@ export interface Device {
|
|||||||
setConfig: (config: Protobuf.Config) => void;
|
setConfig: (config: Protobuf.Config) => void;
|
||||||
setModuleConfig: (config: Protobuf.ModuleConfig) => void;
|
setModuleConfig: (config: Protobuf.ModuleConfig) => void;
|
||||||
setHardware: (hardware: Protobuf.MyNodeInfo) => void;
|
setHardware: (hardware: Protobuf.MyNodeInfo) => void;
|
||||||
setMetrics: (metrics: Types.TelemetryPacket) => void;
|
setMetrics: (metrics: Types.PacketMetadata<Protobuf.Telemetry>) => void;
|
||||||
setActivePage: (page: Page) => void;
|
setActivePage: (page: Page) => void;
|
||||||
setPeerInfoOpen: (open: boolean) => void;
|
setPeerInfoOpen: (open: boolean) => void;
|
||||||
setActivePeer: (peer: number) => void;
|
setActivePeer: (peer: number) => void;
|
||||||
setPendingSettingsChanges: (state: boolean) => void;
|
setPendingSettingsChanges: (state: boolean) => void;
|
||||||
addChannel: (channel: Channel) => void;
|
addChannel: (channel: Channel) => void;
|
||||||
addWaypoint: (waypoint: Protobuf.Waypoint) => void;
|
addWaypoint: (waypoint: Protobuf.Waypoint) => void;
|
||||||
addNodeInfo: (nodeInfo: Types.NodeInfoPacket) => void;
|
addNodeInfo: (nodeInfo: Protobuf.NodeInfo) => void;
|
||||||
addUser: (user: Types.UserPacket) => void;
|
addUser: (user: Types.PacketMetadata<Protobuf.User>) => void;
|
||||||
addPosition: (position: Types.PositionPacket) => void;
|
addPosition: (position: Types.PacketMetadata<Protobuf.Position>) => void;
|
||||||
addConnection: (connection: Types.ConnectionType) => void;
|
addConnection: (connection: Types.ConnectionType) => void;
|
||||||
addMessage: (message: MessageWithState) => void;
|
addMessage: (message: MessageWithState) => void;
|
||||||
addWaypointMessage: (message: WaypointIDWithState) => void;
|
addWaypointMessage: (message: WaypointIDWithState) => void;
|
||||||
addDeviceMetadataMessage: (metadata: Types.DeviceMetadataPacket) => void;
|
addDeviceMetadataMessage: (
|
||||||
|
metadata: Types.PacketMetadata<Protobuf.DeviceMetadata>
|
||||||
|
) => void;
|
||||||
setMessageState: (
|
setMessageState: (
|
||||||
channelIndex: number,
|
channelIndex: number,
|
||||||
messageId: number,
|
messageId: number,
|
||||||
@@ -92,6 +100,7 @@ export interface Device {
|
|||||||
setQRDialogOpen: (open: boolean) => void;
|
setQRDialogOpen: (open: boolean) => void;
|
||||||
setShutdownDialogOpen: (open: boolean) => void;
|
setShutdownDialogOpen: (open: boolean) => void;
|
||||||
setRebootDialogOpen: (open: boolean) => void;
|
setRebootDialogOpen: (open: boolean) => void;
|
||||||
|
processPacket: (data: processPacketParams) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DeviceState {
|
export interface DeviceState {
|
||||||
@@ -237,27 +246,13 @@ export const useDeviceStore = create<DeviceState>((set, get) => ({
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
setMetrics: (metrics: Types.TelemetryPacket) => {
|
setMetrics: (metrics: Types.PacketMetadata<Protobuf.Telemetry>) => {
|
||||||
set(
|
set(
|
||||||
produce<DeviceState>((draft) => {
|
produce<DeviceState>((draft) => {
|
||||||
const device = draft.devices.get(id);
|
const device = draft.devices.get(id);
|
||||||
let node = device?.nodes.find(
|
let node = device?.nodes.find(
|
||||||
(n) => n.data.num === metrics.packet.from
|
(n) => n.data.num === metrics.from
|
||||||
);
|
);
|
||||||
if (device && !node) {
|
|
||||||
node = {
|
|
||||||
data: Protobuf.NodeInfo.create({
|
|
||||||
num: metrics.packet.from,
|
|
||||||
snr: metrics.packet.rxSnr,
|
|
||||||
lastHeard: Date.now()
|
|
||||||
}),
|
|
||||||
metadata: undefined,
|
|
||||||
deviceMetrics: [],
|
|
||||||
environmentMetrics: []
|
|
||||||
};
|
|
||||||
|
|
||||||
device.nodes.push(node);
|
|
||||||
}
|
|
||||||
if (node) {
|
if (node) {
|
||||||
switch (metrics.data.variant.oneofKind) {
|
switch (metrics.data.variant.oneofKind) {
|
||||||
case "deviceMetrics":
|
case "deviceMetrics":
|
||||||
@@ -283,19 +278,13 @@ export const useDeviceStore = create<DeviceState>((set, get) => ({
|
|||||||
}
|
}
|
||||||
node.deviceMetrics.push({
|
node.deviceMetrics.push({
|
||||||
...metrics.data.variant.deviceMetrics,
|
...metrics.data.variant.deviceMetrics,
|
||||||
timestamp:
|
timestamp: metrics.rxTime
|
||||||
metrics.packet.rxTime === 0
|
|
||||||
? new Date()
|
|
||||||
: new Date(metrics.packet.rxTime * 1000)
|
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case "environmentMetrics":
|
case "environmentMetrics":
|
||||||
node.environmentMetrics.push({
|
node.environmentMetrics.push({
|
||||||
...metrics.data.variant.environmentMetrics,
|
...metrics.data.variant.environmentMetrics,
|
||||||
timestamp:
|
timestamp: metrics.rxTime
|
||||||
metrics.packet.rxTime === 0
|
|
||||||
? new Date()
|
|
||||||
: new Date(metrics.packet.rxTime * 1000)
|
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -364,30 +353,18 @@ export const useDeviceStore = create<DeviceState>((set, get) => ({
|
|||||||
set(
|
set(
|
||||||
produce<DeviceState>((draft) => {
|
produce<DeviceState>((draft) => {
|
||||||
const device = draft.devices.get(id);
|
const device = draft.devices.get(id);
|
||||||
if (device) {
|
const node = device?.nodes.find(
|
||||||
const node = device.nodes.find(
|
(node) => node.data.num === nodeInfo.num
|
||||||
(node) => node.data.num === nodeInfo.data.num
|
);
|
||||||
);
|
if (node) {
|
||||||
if (node) {
|
node.data = nodeInfo;
|
||||||
node.data = nodeInfo.data;
|
} else {
|
||||||
node.data.lastHeard =
|
device?.nodes.push({
|
||||||
nodeInfo.packet.rxTime !== 0
|
data: nodeInfo,
|
||||||
? nodeInfo.packet.rxTime * 1000
|
metadata: undefined,
|
||||||
: Date.now();
|
deviceMetrics: [],
|
||||||
} else {
|
environmentMetrics: []
|
||||||
device.nodes.push({
|
});
|
||||||
data: Protobuf.NodeInfo.create({
|
|
||||||
...nodeInfo.data,
|
|
||||||
lastHeard:
|
|
||||||
nodeInfo.packet.rxTime !== 0
|
|
||||||
? nodeInfo.packet.rxTime * 1000
|
|
||||||
: Date.now()
|
|
||||||
}),
|
|
||||||
metadata: undefined,
|
|
||||||
deviceMetrics: [],
|
|
||||||
environmentMetrics: []
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
@@ -416,29 +393,11 @@ export const useDeviceStore = create<DeviceState>((set, get) => ({
|
|||||||
set(
|
set(
|
||||||
produce<DeviceState>((draft) => {
|
produce<DeviceState>((draft) => {
|
||||||
const device = draft.devices.get(id);
|
const device = draft.devices.get(id);
|
||||||
if (device) {
|
const node = device?.nodes.find(
|
||||||
const node = device.nodes.find(
|
(node) => node.data.num === user.from
|
||||||
(node) => node.data.num === user.packet.from
|
);
|
||||||
);
|
if (node) {
|
||||||
if (node) {
|
node.data.user = user.data;
|
||||||
node.data.user = user.data;
|
|
||||||
// if (action.payload.packet.rxTime) {
|
|
||||||
// node.data.lastHeard = new Date(
|
|
||||||
// action.payload.packet.rxTime * 1000,
|
|
||||||
// ).getTime();
|
|
||||||
// }
|
|
||||||
} else {
|
|
||||||
device.nodes.push({
|
|
||||||
data: Protobuf.NodeInfo.create({
|
|
||||||
num: user.packet.from,
|
|
||||||
snr: user.packet.rxSnr,
|
|
||||||
user: user.data
|
|
||||||
}),
|
|
||||||
metadata: undefined,
|
|
||||||
deviceMetrics: [],
|
|
||||||
environmentMetrics: []
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
@@ -447,28 +406,11 @@ export const useDeviceStore = create<DeviceState>((set, get) => ({
|
|||||||
set(
|
set(
|
||||||
produce<DeviceState>((draft) => {
|
produce<DeviceState>((draft) => {
|
||||||
const device = draft.devices.get(id);
|
const device = draft.devices.get(id);
|
||||||
if (device) {
|
const node = device?.nodes.find(
|
||||||
const node = device.nodes.find(
|
(node) => node.data.num === position.from
|
||||||
(node) => node.data.num === position.packet.from
|
);
|
||||||
);
|
if (node) {
|
||||||
if (node) {
|
node.data.position = position.data;
|
||||||
node.data.position = position.data;
|
|
||||||
// if (action.payload.packet.rxTime) {
|
|
||||||
// node.data.lastHeard = new Date(
|
|
||||||
// action.payload.packet.rxTime * 1000,
|
|
||||||
// ).getTime();
|
|
||||||
// }
|
|
||||||
} else {
|
|
||||||
device.nodes.push({
|
|
||||||
data: Protobuf.NodeInfo.create({
|
|
||||||
num: position.packet.from,
|
|
||||||
position: position.data
|
|
||||||
}),
|
|
||||||
metadata: undefined,
|
|
||||||
deviceMetrics: [],
|
|
||||||
environmentMetrics: []
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
@@ -487,11 +429,9 @@ export const useDeviceStore = create<DeviceState>((set, get) => ({
|
|||||||
set(
|
set(
|
||||||
produce<DeviceState>((draft) => {
|
produce<DeviceState>((draft) => {
|
||||||
const device = draft.devices.get(id);
|
const device = draft.devices.get(id);
|
||||||
if (device) {
|
device?.channels
|
||||||
device.channels
|
.find((ch) => ch.config.index === message.channel)
|
||||||
.find((ch) => ch.config.index === message.packet.channel)
|
?.messages.push(message);
|
||||||
?.messages.push(message);
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@@ -499,11 +439,9 @@ export const useDeviceStore = create<DeviceState>((set, get) => ({
|
|||||||
set(
|
set(
|
||||||
produce<DeviceState>((draft) => {
|
produce<DeviceState>((draft) => {
|
||||||
const device = draft.devices.get(id);
|
const device = draft.devices.get(id);
|
||||||
if (device) {
|
device?.channels
|
||||||
device.channels
|
.find((ch) => ch.config.index === waypointID.channel)
|
||||||
.find((ch) => ch.config.index === waypointID.packet.channel)
|
?.messages.push(waypointID);
|
||||||
?.messages.push(waypointID);
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@@ -511,15 +449,11 @@ export const useDeviceStore = create<DeviceState>((set, get) => ({
|
|||||||
set(
|
set(
|
||||||
produce<DeviceState>((draft) => {
|
produce<DeviceState>((draft) => {
|
||||||
const device = draft.devices.get(id);
|
const device = draft.devices.get(id);
|
||||||
if (device) {
|
const node = device?.nodes.find(
|
||||||
const node = device.nodes.find(
|
(n) => n.data.num === metadata.from
|
||||||
(n) => n.data.num === metadata.packet.from
|
);
|
||||||
);
|
if (node) {
|
||||||
if (node) {
|
node.metadata = metadata.data;
|
||||||
node.metadata = metadata.data;
|
|
||||||
} else {
|
|
||||||
console.log("Node not found!");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
@@ -537,7 +471,7 @@ export const useDeviceStore = create<DeviceState>((set, get) => ({
|
|||||||
(ch) => ch.config.index === channelIndex
|
(ch) => ch.config.index === channelIndex
|
||||||
);
|
);
|
||||||
const message = channel?.messages.find(
|
const message = channel?.messages.find(
|
||||||
(msg) => msg.packet.id === messageId
|
(msg) => msg.id === messageId
|
||||||
);
|
);
|
||||||
if (message) {
|
if (message) {
|
||||||
message.state = state;
|
message.state = state;
|
||||||
@@ -584,6 +518,36 @@ export const useDeviceStore = create<DeviceState>((set, get) => ({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
},
|
||||||
|
processPacket(data: processPacketParams) {
|
||||||
|
set(
|
||||||
|
produce<DeviceState>((draft) => {
|
||||||
|
const device = draft.devices.get(id);
|
||||||
|
if (!device) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const node = device.nodes.find((n) => n.data.num === data.from);
|
||||||
|
if (!node) {
|
||||||
|
device.nodes.push({
|
||||||
|
data: Protobuf.NodeInfo.create({
|
||||||
|
num: data.from,
|
||||||
|
lastHeard: data.time,
|
||||||
|
snr: data.snr
|
||||||
|
}),
|
||||||
|
metadata: undefined,
|
||||||
|
deviceMetrics: [],
|
||||||
|
environmentMetrics: []
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
node.data = {
|
||||||
|
...node.data,
|
||||||
|
lastHeard: data.time,
|
||||||
|
snr: data.snr
|
||||||
|
};
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ export const subscribeAll = (
|
|||||||
device.addWaypoint(data);
|
device.addWaypoint(data);
|
||||||
device.addWaypointMessage({
|
device.addWaypointMessage({
|
||||||
waypointID: data.id,
|
waypointID: data.id,
|
||||||
state: rest.packet.from !== myNodeNum ? "ack" : "waiting",
|
state: rest.from !== myNodeNum ? "ack" : "waiting",
|
||||||
...rest
|
...rest
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -84,7 +84,7 @@ export const subscribeAll = (
|
|||||||
});
|
});
|
||||||
|
|
||||||
connection.events.onNodeInfoPacket.subscribe((nodeInfo) => {
|
connection.events.onNodeInfoPacket.subscribe((nodeInfo) => {
|
||||||
toast(`New Node Discovered: ${nodeInfo.data.user?.shortName ?? "UNK"}`, {
|
toast(`New Node Discovered: ${nodeInfo.user?.shortName ?? "UNK"}`, {
|
||||||
icon: "🔎"
|
icon: "🔎"
|
||||||
});
|
});
|
||||||
device.addNodeInfo(nodeInfo);
|
device.addNodeInfo(nodeInfo);
|
||||||
@@ -92,26 +92,34 @@ export const subscribeAll = (
|
|||||||
|
|
||||||
connection.events.onChannelPacket.subscribe((channel) => {
|
connection.events.onChannelPacket.subscribe((channel) => {
|
||||||
device.addChannel({
|
device.addChannel({
|
||||||
config: channel.data,
|
config: channel,
|
||||||
lastInterraction: new Date(),
|
lastInterraction: new Date(),
|
||||||
messages: []
|
messages: []
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
connection.events.onConfigPacket.subscribe((config) => {
|
connection.events.onConfigPacket.subscribe((config) => {
|
||||||
device.setConfig(config.data);
|
device.setConfig(config);
|
||||||
});
|
});
|
||||||
connection.events.onModuleConfigPacket.subscribe((moduleConfig) => {
|
connection.events.onModuleConfigPacket.subscribe((moduleConfig) => {
|
||||||
device.setModuleConfig(moduleConfig.data);
|
device.setModuleConfig(moduleConfig);
|
||||||
});
|
});
|
||||||
|
|
||||||
connection.events.onMessagePacket.subscribe((messagePacket) => {
|
connection.events.onMessagePacket.subscribe((messagePacket) => {
|
||||||
device.addMessage({
|
device.addMessage({
|
||||||
...messagePacket,
|
...messagePacket,
|
||||||
state: messagePacket.packet.from !== myNodeNum ? "ack" : "waiting"
|
state: messagePacket.from !== myNodeNum ? "ack" : "waiting"
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
connection.events.onPendingSettingsChange.subscribe((state) => {
|
connection.events.onPendingSettingsChange.subscribe((state) => {
|
||||||
device.setPendingSettingsChanges(state);
|
device.setPendingSettingsChanges(state);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
connection.events.onMeshPacket.subscribe((meshPacket) => {
|
||||||
|
device.processPacket({
|
||||||
|
from: meshPacket.from,
|
||||||
|
snr: meshPacket.rxSnr,
|
||||||
|
time: meshPacket.rxTime
|
||||||
|
});
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
+5
-1
@@ -12,6 +12,7 @@ import {
|
|||||||
EllipsisHorizontalIcon
|
EllipsisHorizontalIcon
|
||||||
} from "@heroicons/react/24/outline";
|
} from "@heroicons/react/24/outline";
|
||||||
import { Protobuf } from "@meshtastic/meshtasticjs";
|
import { Protobuf } from "@meshtastic/meshtasticjs";
|
||||||
|
import TimeAgo from "timeago-react";
|
||||||
|
|
||||||
export const PeersPage = (): JSX.Element => {
|
export const PeersPage = (): JSX.Element => {
|
||||||
const { connection, nodes } = useDevice();
|
const { connection, nodes } = useDevice();
|
||||||
@@ -98,7 +99,10 @@ export const PeersPage = (): JSX.Element => {
|
|||||||
)}
|
)}
|
||||||
</td>
|
</td>
|
||||||
<td className="whitespace-nowrap py-2 text-sm text-textSecondary">
|
<td className="whitespace-nowrap py-2 text-sm text-textSecondary">
|
||||||
{new Date(node.data.lastHeard).toLocaleTimeString()}
|
<TimeAgo
|
||||||
|
datetime={node.data.lastHeard * 1000}
|
||||||
|
opts={{ minInterval: 10 }}
|
||||||
|
/>
|
||||||
</td>
|
</td>
|
||||||
<td className="whitespace-nowrap py-2 text-sm text-textSecondary">
|
<td className="whitespace-nowrap py-2 text-sm text-textSecondary">
|
||||||
<Mono>{node.data.snr}db</Mono>
|
<Mono>{node.data.snr}db</Mono>
|
||||||
|
|||||||
Reference in New Issue
Block a user