diff --git a/src/apiDocs/enumerators/generalEnums.tsx b/src/apiDocs/enumerators/generalEnums.tsx index 873cd95..c52974b 100644 --- a/src/apiDocs/enumerators/generalEnums.tsx +++ b/src/apiDocs/enumerators/generalEnums.tsx @@ -555,10 +555,10 @@ const componentType: data = { key: "COMPONENT_TYPE_CAPACITANCE", val: 24 }, - { - key: "COMPONENT_TYPE_VAPOUR_PRESSURE_DEFICIT", - val: 25 - }, + // { + // key: "COMPONENT_TYPE_VAPOUR_PRESSURE_DEFICIT", //this component type is deprecated? + // val: 25 + // }, { key: "COMPONENT_TYPE_WEIGHT", val: 26 diff --git a/src/bin/BinComponents.tsx b/src/bin/BinComponents.tsx index 33a912a..f99e349 100644 --- a/src/bin/BinComponents.tsx +++ b/src/bin/BinComponents.tsx @@ -414,7 +414,7 @@ export default function BinComponents(props: Props) { )} - {comp.name()} + {comp.name() + " " + comp.addressDescription(devMap.get(device)?.settings.product)} {components?.get(comp.key()) !== undefined ? ( diff --git a/src/device/DeviceWizard.tsx b/src/device/DeviceWizard.tsx index d426c21..4de3cc2 100644 --- a/src/device/DeviceWizard.tsx +++ b/src/device/DeviceWizard.tsx @@ -26,7 +26,8 @@ import { import { GetDeviceProductIcon, GetDeviceProductLabel } from "products/DeviceProduct"; import { pond } from "protobuf-ts/pond"; import { quack } from "protobuf-ts/quack"; -import { useComponentAPI, useGlobalState, useSnackbar } from "providers"; +import { useComponentAPI, useDeviceAPI, useGlobalState, useSnackbar } from "providers"; + import React, { useState } from "react"; import DeviceSVG, { PortInformation } from "./deviceSVG"; import { makeStyles } from "@mui/styles"; @@ -83,6 +84,8 @@ export default function DeviceWizard(props: Props) { ); const classes = useStyles(); const [selectedPort, setSelectedPort] = useState(); + const deviceAPI = useDeviceAPI() + const { openSnack } = useSnackbar() //const [addressType, setAddressType] = useState(quack.AddressType.ADDRESS_TYPE_CONFIGURABLE_PIN_ARRAY); const wizardMenu = () => { @@ -118,6 +121,22 @@ export default function DeviceWizard(props: Props) { )} + {selectedPort && selectedPort.addressType === quack.AddressType.ADDRESS_TYPE_I2C && device.featureSupported("detectI2C") && ( + + { + deviceAPI.detectI2C(device.id()) + .then(resp => { + openSnack("Device will scan port on next check-in") + }).catch(err => { + openSnack("Command failed to send to device") + }) + }}> + Scan Port + + + )} {portComponents.length > 0 && ( Current Components diff --git a/src/device/autoDetect/DeviceScannedComponents.tsx b/src/device/autoDetect/DeviceScannedComponents.tsx new file mode 100644 index 0000000..e706da0 --- /dev/null +++ b/src/device/autoDetect/DeviceScannedComponents.tsx @@ -0,0 +1,93 @@ +import { Box, Card, DialogContent, FormControlLabel, Radio, RadioGroup, Step, StepLabel, Stepper } from "@mui/material"; +import { cloneDeep } from "lodash"; +import { getSubtypes, Subtype } from "pbHelpers/ComponentType"; +import { pond, quack } from "protobuf-ts/pond"; +import React from "react"; +import { useEffect, useState } from "react"; +import ScannedI2C from "./ScannedI2C"; +import ComponentForm from "component/ComponentForm"; +import { Component, Device } from "models"; + +interface Props { + scannedComponents: pond.ComponentAddressMap + device: Device +} + +interface CompStep { + label: string; + completed?: boolean; +} + +export default function DeviceScannedComponents(props: Props){ + const {scannedComponents, device} = props + const [scannedI2C, setScannedI2C] = useState() + const [components, setComponents] = useState([]) + const [steps, setSteps] = useState([]); + const [currentStep, setCurrentStep] = useState(0) + const [settingsValid, setSettingsValid] = useState(false); + + useEffect(()=>{ + if (scannedComponents.i2c) setScannedI2C(scannedComponents.i2c) + },[scannedComponents]) + + useEffect(() => { + let steps: CompStep[] = [] + components.forEach(comp => { + steps.push({ + label: comp.name(), + completed: false + }) + }) + },[components]) + + const stepper = () => { + return ( + + {steps.map(compStep => { + const labelProps: { + optional?: React.ReactNode; + } = {}; + return ( + + {compStep.label} + + ); + })} + + ); + }; + + const addComponentContent = () => { + return ( + + {stepper()} + { + components[currentStep].settings = component.settings; + setSettingsValid(isValid); + }} + /> + + ); + }; + + + + return ( + + {scannedI2C && + + I2C Components Found + {scannedI2C?.settings?.foundAddresses.map((addr, index) => { + return ( + {}} /> + ) + })} + + } + + ) +} \ No newline at end of file diff --git a/src/device/autoDetect/ScannedI2C.tsx b/src/device/autoDetect/ScannedI2C.tsx new file mode 100644 index 0000000..ff057d4 --- /dev/null +++ b/src/device/autoDetect/ScannedI2C.tsx @@ -0,0 +1,107 @@ +import { Box, Button, FormControlLabel, MenuItem, Radio, RadioGroup, TextField } from "@mui/material"; +import { getAddressTypes, getFriendlyName, getSubtypes, Subtype } from "pbHelpers/ComponentType"; +import { GetProductAvailability } from "products/DeviceProduct"; +import { pond } from "protobuf-ts/pond"; +import { quack } from "protobuf-ts/quack"; +import { useEffect, useState } from "react"; + +interface Props { + decimalAddress: number + deviceProduct: pond.DeviceProduct + updateComponentList: () => void +} + +export default function ScannedI2C(props: Props){ + const {decimalAddress, deviceProduct} = props + const [types, setTypes] = useState([]) + const [subtypeOptions, setSubtypeOptions] = useState>([]) + const [selectedType, setSelectedType] = useState(quack.ComponentType.COMPONENT_TYPE_INVALID) + const [selectedSubtype, setSelectedSubtype] = useState(0) + + useEffect(()=>{ + //convert the address to hex + let hexAddress = parseInt(decimalAddress.toString(16)) + hexAddress = 0x2a //hardcoding for testing + let types: quack.ComponentType[] = [] + //find what component types use that address + let productAvailability = GetProductAvailability(deviceProduct) + if(productAvailability){ + let i2cMap = productAvailability.get(quack.AddressType.ADDRESS_TYPE_I2C) + if(i2cMap){ + i2cMap.forEach((val, key) => { + let addresses = val as number[] ?? [] + if(addresses.length > 0 && addresses.includes(hexAddress)){ + types.push(key) + } + }) + } + } + //this if can be taken out if we dont want to select the first component type by default + if(types.length > 0) { + setSelectedType(types[0]) + buildSubtypeOptions(types[0]) + } + setTypes(types) + },[decimalAddress, deviceProduct]) + + const buildSubtypeOptions = (compType: quack.ComponentType) => { + let subtypes = getSubtypes(compType) + let validSub: Subtype[] = [] + //have to exclude subtypes that are not I2C + subtypes.forEach((sub,i) => { + let addrTypes = getAddressTypes(compType, sub.key) + if (addrTypes.includes(quack.AddressType.ADDRESS_TYPE_I2C)){ + validSub.push(sub) + } + }) + //set the selected on to be the first in the valid selection + if(validSub.length > 0){ + setSelectedSubtype(validSub[0].key) + } + setSubtypeOptions(validSub) + } + + + + return ( + + Sensor 1 + { + console.log(value) + let v = parseInt(value) + if (!isNaN(v)){ + buildSubtypeOptions(v) + } + }}> + {types.map((type, i) => { + return ( + } + label={getFriendlyName(type)} + /> + ) + })} + + {subtypeOptions.length > 0 && + { + let val = +event.target.value + console.log(event.target.value) + setSelectedSubtype(val) + }} + select> + {subtypeOptions.map(s => ( + {s.friendlyName} + ))} + + } + + + ) +} \ No newline at end of file diff --git a/src/models/Component.ts b/src/models/Component.ts index c9bbc2c..84f5574 100644 --- a/src/models/Component.ts +++ b/src/models/Component.ts @@ -3,6 +3,7 @@ import { quack } from "protobuf-ts/pond"; import { or } from "utils/types"; import { cloneDeep } from "lodash"; import { getSubtypes } from "pbHelpers/ComponentType"; +import { getFriendlyAddressTypeName, getHumanReadableAddress } from "pbHelpers/AddressType"; // import { getSubtypes } from "pbHelpers/ComponentType"; export class Component { @@ -105,4 +106,33 @@ export class Component { } return 0; } + + public addressDescription = (deviceProduct?: pond.DeviceProduct) => { + if ( + this.settings.addressType === quack.AddressType.ADDRESS_TYPE_CONFIGURABLE_PIN_ARRAY || + (this.settings.addressType >= quack.AddressType.ADDRESS_TYPE_PIN_OFFSET1 && + this.settings.addressType <= quack.AddressType.ADDRESS_TYPE_PIN_OFFSET100) + ) { + let addressDescription = getHumanReadableAddress( + this.settings.addressType, + this.settings.type, + this.settings.address, + deviceProduct + ); + if (addressDescription === "") { + addressDescription = "Internal"; + } + let port = "Port: " + addressDescription; + let cableID = ""; + if ( + this.settings.addressType >= quack.AddressType.ADDRESS_TYPE_PIN_OFFSET1 && + this.settings.addressType <= quack.AddressType.ADDRESS_TYPE_PIN_OFFSET100 + ) { + cableID = "Cable: " + (this.settings.addressType - 8); + } + return port + " " + cableID; + } else { + return getFriendlyAddressTypeName(this.settings.addressType); + } + }; } diff --git a/src/models/Device.ts b/src/models/Device.ts index b201407..6311981 100644 --- a/src/models/Device.ts +++ b/src/models/Device.ts @@ -33,6 +33,21 @@ const featureVersions: Map = new Map([ v2CellBlue: "2.0.44", v2EthBlue: "2.0.44" } + ],[ + "detectI2C", + { + photon: "NA", + electron: "NA", + v2Wifi: "2.1.6", + v2Cell: "2.1.6", + v2WifiS3: "2.1.6", + v2CellS3: "2.1.6", + v2CellBlack: "2.1.6", + v2CellGreen: "2.1.6", + v2WifiBlue: "2.1.6", + v2CellBlue: "2.1.6", + v2EthBlue: "2.1.6" + } ] ]); export class Device { diff --git a/src/pages/Device.tsx b/src/pages/Device.tsx index e50469b..6b36115 100644 --- a/src/pages/Device.tsx +++ b/src/pages/Device.tsx @@ -1,4 +1,4 @@ -import { Button, Divider, List, ListItem, Typography } from "@mui/material"; +import { Button, Card, Divider, List, ListItem, Typography } from "@mui/material"; import Grid from '@mui/material/Grid2'; import { Component, Device, Interaction, User } from "models"; import { getContextKeys, getContextTypes } from "pbHelpers/Context"; @@ -20,6 +20,7 @@ import { isController } from "pbHelpers/ComponentType"; import { or } from "utils"; import ComponentDiagnostics from "component/ComponentDiagnostics"; import DeviceWizard from "device/DeviceWizard"; +import DeviceScannedComponents from "device/autoDetect/DeviceScannedComponents"; export interface DevicePageData { device: Device; @@ -56,6 +57,7 @@ export default function DevicePage() { const [components, setComponents] = useState>(new Map()); const [diagnosticComponents, setDiagnosticComponents] = useState([]); + const [scannedAddresses, setScannedAddresses] = useState(undefined) // const [components, setComponents] = useState([]); const [addComponentManualDialogOpen, setAddComponentManualDialogOpen] = useState(false) @@ -162,8 +164,19 @@ export default function DevicePage() { .finally(() => setLoading(false)); } + const loadPortScan = () => { + deviceAPI.listFoundComponents(device.id()) + .then(resp => { + setScannedAddresses(resp.data.foundComponents ?? undefined) + }) + .catch(err => { + console.log(err) + }) + } + useEffect(() => { loadDevice() + loadPortScan() }, [deviceID, as]) const toggleNotificationPreference = () => { @@ -404,7 +417,7 @@ export default function DevicePage() { ) : ( <> - + - - + {scannedAddresses && + + + + } + {diagnosticComponents.length > 0 && + + {diagnosticComponents.map(comp => ( - + + } )} diff --git a/src/pbHelpers/AddressTypes/I2C.ts b/src/pbHelpers/AddressTypes/I2C.ts index 7012eee..c17c743 100644 --- a/src/pbHelpers/AddressTypes/I2C.ts +++ b/src/pbHelpers/AddressTypes/I2C.ts @@ -12,7 +12,7 @@ export const I2C: AddressTypeExtension = { [quack.ComponentType.COMPONENT_TYPE_STEPPER_MOTOR, 0x13], [quack.ComponentType.COMPONENT_TYPE_PH, 0x3f], [quack.ComponentType.COMPONENT_TYPE_DHT, 0x3f], - [quack.ComponentType.COMPONENT_TYPE_VAPOUR_PRESSURE_DEFICIT, 0x3f], + // [quack.ComponentType.COMPONENT_TYPE_VAPOUR_PRESSURE_DEFICIT, 0x3f], //component type deprecated? [quack.ComponentType.COMPONENT_TYPE_CAPACITANCE, 0x4f], [quack.ComponentType.COMPONENT_TYPE_CAPACITOR_CABLE, 0x4f], [quack.ComponentType.COMPONENT_TYPE_SEN5X, 0x68], diff --git a/src/pbHelpers/DeviceAvailability.ts b/src/pbHelpers/DeviceAvailability.ts index 84cfa7e..c50a2a4 100644 --- a/src/pbHelpers/DeviceAvailability.ts +++ b/src/pbHelpers/DeviceAvailability.ts @@ -54,7 +54,7 @@ const DefaultAvailability: DeviceAvailabilityMap = new Map([ [quack.ComponentType.COMPONENT_TYPE_PRESSURE, [0x18]], [quack.ComponentType.COMPONENT_TYPE_DHT, [0x40]], - [quack.ComponentType.COMPONENT_TYPE_VAPOUR_PRESSURE_DEFICIT, [0x40]], + // [quack.ComponentType.COMPONENT_TYPE_VAPOUR_PRESSURE_DEFICIT, [0x40]], //component type deprecated? [quack.ComponentType.COMPONENT_TYPE_LIDAR, [0x62]], [quack.ComponentType.COMPONENT_TYPE_CO2, [0x61]], [quack.ComponentType.COMPONENT_TYPE_SEN5X, [0x69]] @@ -48,7 +48,7 @@ export const BindaptPlusModAvailability: DeviceAvailabilityMap = new Map< new Map([ //[quack.ComponentType.COMPONENT_TYPE_PRESSURE, [0x18]], [quack.ComponentType.COMPONENT_TYPE_DHT, [0x40]], - [quack.ComponentType.COMPONENT_TYPE_VAPOUR_PRESSURE_DEFICIT, [0x40]], + // [quack.ComponentType.COMPONENT_TYPE_VAPOUR_PRESSURE_DEFICIT, [0x40]], //component type deprecated? [quack.ComponentType.COMPONENT_TYPE_LIDAR, [0x62]], [quack.ComponentType.COMPONENT_TYPE_CO2, [0x61]], [quack.ComponentType.COMPONENT_TYPE_SEN5X, [0x69]] @@ -78,10 +78,11 @@ export const BindaptPlusProAvailability: DeviceAvailabilityMap = new Map< new Map([ [quack.ComponentType.COMPONENT_TYPE_PRESSURE, [0x18]], [quack.ComponentType.COMPONENT_TYPE_DHT, [0x40]], - [quack.ComponentType.COMPONENT_TYPE_VAPOUR_PRESSURE_DEFICIT, [0x40]], + // [quack.ComponentType.COMPONENT_TYPE_VAPOUR_PRESSURE_DEFICIT, [0x40]], [quack.ComponentType.COMPONENT_TYPE_LIDAR, [0x62]], [quack.ComponentType.COMPONENT_TYPE_CO2, [0x61]], - [quack.ComponentType.COMPONENT_TYPE_SEN5X, [0x69]] + [quack.ComponentType.COMPONENT_TYPE_SEN5X, [0x69]], + [quack.ComponentType.COMPONENT_TYPE_AIRFLOW, [0x2a]] ]) ], [quack.AddressType.ADDRESS_TYPE_POWER, [0]], @@ -109,7 +110,7 @@ export const BindaptPlusProModAvailability: DeviceAvailabilityMap = new Map< new Map([ //[quack.ComponentType.COMPONENT_TYPE_PRESSURE, [0x18]], [quack.ComponentType.COMPONENT_TYPE_DHT, [0x40]], - [quack.ComponentType.COMPONENT_TYPE_VAPOUR_PRESSURE_DEFICIT, [0x40]], + // [quack.ComponentType.COMPONENT_TYPE_VAPOUR_PRESSURE_DEFICIT, [0x40]], //component type deprecated? [quack.ComponentType.COMPONENT_TYPE_LIDAR, [0x62]], [quack.ComponentType.COMPONENT_TYPE_CO2, [0x61]], [quack.ComponentType.COMPONENT_TYPE_SEN5X, [0x69]] @@ -136,7 +137,7 @@ export const BindaptPlusLiteAvailability: DeviceAvailabilityMap = new Map< new Map([ [quack.ComponentType.COMPONENT_TYPE_PRESSURE, [0x18]], [quack.ComponentType.COMPONENT_TYPE_DHT, [0x40]], - [quack.ComponentType.COMPONENT_TYPE_VAPOUR_PRESSURE_DEFICIT, [0x40]], + // [quack.ComponentType.COMPONENT_TYPE_VAPOUR_PRESSURE_DEFICIT, [0x40]], //component type deprecated? [quack.ComponentType.COMPONENT_TYPE_LIDAR, [0x62]], [quack.ComponentType.COMPONENT_TYPE_CO2, [0x61]], [quack.ComponentType.COMPONENT_TYPE_SEN5X, [0x69]] @@ -192,7 +193,7 @@ export const BindaptUltimateAvailability: DeviceAvailabilityMap = new Map< new Map([ [quack.ComponentType.COMPONENT_TYPE_PRESSURE, [0x18]], [quack.ComponentType.COMPONENT_TYPE_DHT, [0x40]], - [quack.ComponentType.COMPONENT_TYPE_VAPOUR_PRESSURE_DEFICIT, [0x40]], + // [quack.ComponentType.COMPONENT_TYPE_VAPOUR_PRESSURE_DEFICIT, [0x40]], //component type deprecated? [quack.ComponentType.COMPONENT_TYPE_LIDAR, [0x62]], [quack.ComponentType.COMPONENT_TYPE_CO2, [0x61]], [quack.ComponentType.COMPONENT_TYPE_SEN5X, [0x69]] @@ -219,7 +220,7 @@ export const BinMonitorAvailability: DeviceAvailabilityMap = new Map< new Map([ [quack.ComponentType.COMPONENT_TYPE_PRESSURE, [0x18]], [quack.ComponentType.COMPONENT_TYPE_DHT, [0x40]], - [quack.ComponentType.COMPONENT_TYPE_VAPOUR_PRESSURE_DEFICIT, [0x40]], + // [quack.ComponentType.COMPONENT_TYPE_VAPOUR_PRESSURE_DEFICIT, [0x40]], //component type deprecated? [quack.ComponentType.COMPONENT_TYPE_LIDAR, [0x62]], [quack.ComponentType.COMPONENT_TYPE_CO2, [0x61]] ]) @@ -248,7 +249,7 @@ export const BindaptV2MonitorAvailability: DeviceAvailabilityMap = new Map< new Map([ //[quack.ComponentType.COMPONENT_TYPE_PRESSURE, [0x18]], [quack.ComponentType.COMPONENT_TYPE_DHT, [0x40]], - [quack.ComponentType.COMPONENT_TYPE_VAPOUR_PRESSURE_DEFICIT, [0x40]], + // [quack.ComponentType.COMPONENT_TYPE_VAPOUR_PRESSURE_DEFICIT, [0x40]], //component type deprecated? [quack.ComponentType.COMPONENT_TYPE_LIDAR, [0x62]], [quack.ComponentType.COMPONENT_TYPE_CO2, [0x61]], [quack.ComponentType.COMPONENT_TYPE_SEN5X, [0x69]] @@ -280,7 +281,7 @@ export const BindaptV2AutomateAvailability: DeviceAvailabilityMap = new Map< new Map([ //[quack.ComponentType.COMPONENT_TYPE_PRESSURE, [0x18]], [quack.ComponentType.COMPONENT_TYPE_DHT, [0x40]], - [quack.ComponentType.COMPONENT_TYPE_VAPOUR_PRESSURE_DEFICIT, [0x40]], + // [quack.ComponentType.COMPONENT_TYPE_VAPOUR_PRESSURE_DEFICIT, [0x40]], //component type deprecated? [quack.ComponentType.COMPONENT_TYPE_LIDAR, [0x62]], [quack.ComponentType.COMPONENT_TYPE_CO2, [0x61]], [quack.ComponentType.COMPONENT_TYPE_SEN5X, [0x69]] diff --git a/src/products/DeviceProduct.ts b/src/products/DeviceProduct.ts index 792be79..844e0be 100644 --- a/src/products/DeviceProduct.ts +++ b/src/products/DeviceProduct.ts @@ -64,7 +64,7 @@ const Weather: DeviceProductDescriber = { new Map([ [quack.ComponentType.COMPONENT_TYPE_PRESSURE, [0x18]], [quack.ComponentType.COMPONENT_TYPE_DHT, [0x40]], - [quack.ComponentType.COMPONENT_TYPE_VAPOUR_PRESSURE_DEFICIT, [0x40]], + // [quack.ComponentType.COMPONENT_TYPE_VAPOUR_PRESSURE_DEFICIT, [0x40]], //deprecated? [quack.ComponentType.COMPONENT_TYPE_LIDAR, [0x62]] ]) ], diff --git a/src/products/Nexus/NexusAvailability.ts b/src/products/Nexus/NexusAvailability.ts index 9f9fc57..2a1cf51 100644 --- a/src/products/Nexus/NexusAvailability.ts +++ b/src/products/Nexus/NexusAvailability.ts @@ -20,7 +20,7 @@ export const NexusSTAvailability: DeviceAvailabilityMap = new Map< new Map([ [quack.ComponentType.COMPONENT_TYPE_PRESSURE, [0x18]], [quack.ComponentType.COMPONENT_TYPE_DHT, [0x40]], - [quack.ComponentType.COMPONENT_TYPE_VAPOUR_PRESSURE_DEFICIT, [0x40]], + // [quack.ComponentType.COMPONENT_TYPE_VAPOUR_PRESSURE_DEFICIT, [0x40]], //component type deprecated? [quack.ComponentType.COMPONENT_TYPE_LIDAR, [0x62]], [quack.ComponentType.COMPONENT_TYPE_SEN5X, [0x69]] ]) diff --git a/src/providers/pond/deviceAPI.tsx b/src/providers/pond/deviceAPI.tsx index 7b7384c..f42133f 100644 --- a/src/providers/pond/deviceAPI.tsx +++ b/src/providers/pond/deviceAPI.tsx @@ -23,7 +23,7 @@ export interface IDeviceAPIContext { ) => Promise>; getMulti: (ids: number[] | string[], otherTeam?: string) => Promise>; detectI2C: (id: number, otherTeam?: string) => Promise>; - listFoundComponents: (is: number, otherTeam?: string) => Promise> + listFoundComponents: (id: number, otherTeam?: string) => Promise> getGeoJson: (id: number | string, demo?: boolean, otherTeam?: string) => Promise; getMultiGeoJson: (ids: number[] | string[], otherTeam?: string) => Promise; list: (