Add maps, Bluetooth config & fixes

This commit is contained in:
Sacha Weatherstone
2022-08-19 18:18:48 +09:30
parent b8877f8a63
commit 9f1d3498ea
44 changed files with 611 additions and 1064 deletions
+1 -1
View File
@@ -19,7 +19,7 @@ import {
import { Controller, useForm } from "react-hook-form";
import { Form } from "@components/form/Form";
import { useDevice } from "@core/stores/deviceStore.js";
import { useDevice } from "@core/providers/useDevice.js";
import { Protobuf } from "@meshtastic/meshtasticjs";
export interface SettingsPanelProps {
+1 -1
View File
@@ -6,7 +6,7 @@ import { IoQrCodeOutline } from "react-icons/io5";
import { QRDialog } from "@app/components/Dialog/QRDialog.js";
import { TabbedContent, TabType } from "@components/layout/page/TabbedContent";
import { useDevice } from "@core/stores/deviceStore.js";
import { useDevice } from "@core/providers/useDevice.js";
import { Protobuf } from "@meshtastic/meshtasticjs";
import { Channel } from "./Channel.js";
+6 -3
View File
@@ -3,7 +3,7 @@ import { useState } from "react";
import { Pane, Tab, Tablist } from "evergreen-ui";
import { useDevice } from "@app/core/stores/deviceStore.js";
import { Bluetooth } from "@app/components/PageComponents/Config/Bluetooth.js";
import { Device } from "@components/PageComponents/Config/Device.js";
import { Display } from "@components/PageComponents/Config/Display.js";
import { LoRa } from "@components/PageComponents/Config/LoRa.js";
@@ -11,6 +11,7 @@ import { Position } from "@components/PageComponents/Config/Position.js";
import { Power } from "@components/PageComponents/Config/Power.js";
import { User } from "@components/PageComponents/Config/User.js";
import { WiFi } from "@components/PageComponents/Config/WiFi.js";
import { useDevice } from "@core/providers/useDevice.js";
export const DeviceConfig = (): JSX.Element => {
const [selectedIndex, setSelectedIndex] = useState(0);
@@ -46,8 +47,10 @@ export const DeviceConfig = (): JSX.Element => {
label: "LoRa",
element: LoRa,
},
// Channels
// Interface
{
label: "Bluetooth",
element: Bluetooth,
},
];
return (
+1 -1
View File
@@ -2,7 +2,7 @@ import type React from "react";
import { Pane } from "evergreen-ui";
import { useDevice } from "@app/core/stores/deviceStore.js";
import { useDevice } from "@core/providers/useDevice.js";
export const Environment = (): JSX.Element => {
const { nodes } = useDevice();
+10 -7
View File
@@ -1,9 +1,7 @@
import type React from "react";
import { useEffect, useState } from "react";
import { Pane } from "evergreen-ui";
import useSWR from "swr";
import { fetcher } from "@core/utils/fetcher";
export interface File {
nameModified: string;
@@ -24,10 +22,15 @@ export interface Files {
}
export const FileBrowser = (): JSX.Element => {
const { data } = useSWR<Files>(
"http://meshtastic.local/json/fs/browse/static",
fetcher
);
const [data, setData] = useState<Files>();
useEffect(() => {
void fetch("http://meshtastic.local/json/fs/browse/static").then(
async (res) => {
setData((await res.json()) as Files);
}
);
});
return (
<Pane>
+1 -1
View File
@@ -2,8 +2,8 @@ import type React from "react";
import { DocumentIcon, GanttChartIcon, RainIcon } from "evergreen-ui";
import { useDevice } from "@app/core/stores/deviceStore.js";
import { TabbedContent, TabType } from "@components/layout/page/TabbedContent";
import { useDevice } from "@core/providers/useDevice.js";
import { FileBrowser } from "@pages/Extensions/FileBrowser";
import { Environment } from "./Environment.js";
+1 -1
View File
@@ -3,7 +3,7 @@ import type React from "react";
import { Pane } from "evergreen-ui";
import JSONPretty from "react-json-pretty";
import { useDevice } from "@app/core/stores/deviceStore.js";
import { useDevice } from "@core/providers/useDevice.js";
export const InfoPage = (): JSX.Element => {
const { hardware, nodes } = useDevice();
+49 -123
View File
@@ -1,137 +1,63 @@
import type React from "react";
import { useEffect, useMemo, useRef } from "react";
import { Pane } from "evergreen-ui";
import { majorScale, Pane } from "evergreen-ui";
import { Marker } from "maplibre-gl";
import { useDevice } from "@app/core/stores/deviceStore.js";
import Point from "@arcgis/core/geometry/Point";
import Graphic from "@arcgis/core/Graphic";
import FeatureLayer from "@arcgis/core/layers/FeatureLayer";
import LabelClass from "@arcgis/core/layers/support/LabelClass";
import Map from "@arcgis/core/Map";
import LineCallout3D from "@arcgis/core/symbols/callouts/LineCallout3D";
import LabelSymbol3D from "@arcgis/core/symbols/LabelSymbol3D";
import TextSymbol3DLayer from "@arcgis/core/symbols/TextSymbol3DLayer";
import SceneView from "@arcgis/core/views/SceneView";
import { useCreateMapbox } from "@app/core/providers/useCreateMapbox.js";
import { useDevice } from "@core/providers/useDevice.js";
export const MapPage = (): JSX.Element => {
const { nodes } = useDevice();
const nodesWithPosition = nodes.filter((node) => node.data.position);
const nodeMarkers = useMemo(() => new Map<number, Marker>(), []);
const ref = useRef<HTMLDivElement>(null);
useEffect(() => {
console.log(nodesWithPosition);
}, [nodesWithPosition]);
const labelClass = useMemo(
() =>
new LabelClass({
labelExpressionInfo: {
expression: "$feature.name",
},
symbol: new LabelSymbol3D({
symbolLayers: [
new TextSymbol3DLayer({
text: "{name}",
material: {
color: "black",
},
halo: {
color: [255, 255, 255, 0.7],
size: 2,
},
font: {
size: 12,
weight: "bold",
},
size: 10,
}),
],
verticalOffset: {
screenLength: 150,
maxWorldLength: 2000,
minWorldLength: 30,
},
callout: new LineCallout3D({
size: 0.5,
color: [0, 0, 0],
border: {
color: [255, 255, 255],
},
}),
}),
}),
[]
);
const points: Graphic[] = nodesWithPosition.map(
(node, index) =>
node.data.position
? new Graphic({
geometry: new Point({
latitude: node.data.position.latitudeI / 1e7,
longitude: node.data.position.longitudeI / 1e7,
}),
attributes: {
ObjectID: index,
name: node.data.user?.longName,
},
})
: new Graphic() //should be undefined/removed from array
);
const map = useCreateMapbox({
ref,
style:
"https://raw.githubusercontent.com/hc-oss/maplibre-gl-styles/master/styles/osm-mapnik/v8/default.json",
});
useEffect(() => {
if (ref.current) {
const layer = new FeatureLayer({
labelsVisible: true,
labelingInfo: [labelClass],
source: points,
fields: [
{
name: "ObjectID",
alias: "ObjectID",
type: "oid",
},
{
name: "name",
alias: "Name",
type: "string",
},
],
});
nodes.map((n) => {
if (n.data.position?.longitudeI && n.data.position?.latitudeI && map) {
if (nodeMarkers.has(n.data.num)) {
nodeMarkers
.get(n.data.num)
?.setLngLat([
n.data.position?.longitudeI / 1e7,
n.data.position?.latitudeI / 1e7,
]);
} else {
nodeMarkers.set(
n.data.num,
new Marker()
.setLngLat([
n.data.position?.longitudeI / 1e7,
n.data.position?.latitudeI / 1e7,
])
.addTo(map)
);
}
}
});
}, [map, nodeMarkers, nodes]);
const map = new Map({
basemap: "satellite",
ground: "world-elevation",
layers: [layer],
});
const scene = new SceneView({
container: ref.current,
map: map,
camera: {
position: nodesWithPosition[0]
? {
x: nodesWithPosition[0].data.position?.longitudeI ?? 0 / 1e7,
y: nodesWithPosition[0].data.position?.latitudeI ?? 0 / 1e7,
z: nodesWithPosition[0].data.position?.altitude ?? 0 / 1e7,
}
: {
y: -35.59, //Longitude
x: 148, //Latitude
z: 200, //Meters
},
tilt: 75,
},
});
scene.on("click", (event) => {
void scene.hitTest(event).then((point) => {
console.log(point);
});
});
}
}, [labelClass, points]);
return <Pane width="100%" height="100%" ref={ref} />;
return (
<Pane
margin={majorScale(3)}
borderRadius={majorScale(1)}
background="white"
elevation={1}
display="flex"
flexGrow={1}
flexDirection="column"
gap={majorScale(2)}
overflow="hidden"
>
<Pane width="100%" height="100%" ref={ref} />
</Pane>
);
};
+1 -1
View File
@@ -12,8 +12,8 @@ import {
Tooltip,
} from "evergreen-ui";
import { useDevice } from "@core/providers/useDevice.js";
import type { Channel } from "@core/stores/deviceStore.js";
import { useDevice } from "@core/stores/deviceStore.js";
import { Message } from "./Message.js";
import { NewLocationMessage } from "./NewLocationMessage.js";
+1 -1
View File
@@ -10,7 +10,7 @@ import {
Text,
} from "evergreen-ui";
import { useDevice } from "@app/core/stores/deviceStore.js";
import { useDevice } from "@core/providers/useDevice.js";
import { Hashicon } from "@emeraldpay/hashicon-react";
import type { Protobuf, Types } from "@meshtastic/meshtasticjs";
+1 -1
View File
@@ -8,8 +8,8 @@ import {
TextInputField,
} from "evergreen-ui";
import { useDevice } from "@app/core/stores/deviceStore.js";
import { renderOptions } from "@app/core/utils/selectEnumOptions.js";
import { useDevice } from "@core/providers/useDevice.js";
import { Protobuf } from "@meshtastic/meshtasticjs";
enum LocationType {
+1 -1
View File
@@ -13,7 +13,7 @@ import {
TabbedContent,
TabType,
} from "@components/layout/page/TabbedContent.js";
import { useDevice } from "@core/stores/deviceStore.js";
import { useDevice } from "@core/providers/useDevice.js";
import { Protobuf } from "@meshtastic/meshtasticjs";
import { ChannelChat } from "./ChannelChat.js";