From c5a3487db0d93e11bb5c8ee169a563d9b2bcea74 Mon Sep 17 00:00:00 2001 From: csawatzky Date: Thu, 30 Oct 2025 16:49:00 -0600 Subject: [PATCH 01/11] added button to send down the onewire scan request --- package-lock.json | 4 +-- package.json | 2 +- src/device/DeviceWizard.tsx | 22 ++++++++++++++++ .../autoDetect/DeviceScannedComponents.tsx | 26 ++++++++++++++++--- src/device/autoDetect/ScannedOneWirePort.tsx | 7 +++++ src/models/Device.ts | 15 +++++++++++ src/pages/Device.tsx | 9 ++++--- src/providers/pond/deviceAPI.tsx | 15 +++++++++++ 8 files changed, 89 insertions(+), 11 deletions(-) create mode 100644 src/device/autoDetect/ScannedOneWirePort.tsx diff --git a/package-lock.json b/package-lock.json index 2f6f8fc..8bf5f65 100644 --- a/package-lock.json +++ b/package-lock.json @@ -42,7 +42,7 @@ "mui-tel-input": "^7.0.0", "notistack": "^3.0.1", "openweathermap-ts": "^1.2.10", - "protobuf-ts": "git+https://gitlab+deploy-token-50627:hv8mB4WkyvtjBpJKU1rN@gitlab.com/brandx/protobuf-ts.git#i2c_detect", + "protobuf-ts": "git+https://gitlab+deploy-token-50627:hv8mB4WkyvtjBpJKU1rN@gitlab.com/brandx/protobuf-ts.git#onewire_detect", "query-string": "^9.2.1", "react": "^18.3.1", "react-beautiful-dnd": "^13.1.1", @@ -10953,7 +10953,7 @@ }, "node_modules/protobuf-ts": { "version": "1.0.0", - "resolved": "git+https://gitlab+deploy-token-50627:hv8mB4WkyvtjBpJKU1rN@gitlab.com/brandx/protobuf-ts.git#0d0084ce207218ea5c8c94addfbf009814c35a1f", + "resolved": "git+https://gitlab+deploy-token-50627:hv8mB4WkyvtjBpJKU1rN@gitlab.com/brandx/protobuf-ts.git#aab2a77a75ca78e22d69d4a44e1c900bbac41bcf", "dependencies": { "protobufjs": "^6.8.8" } diff --git a/package.json b/package.json index c3e3fdc..c73e616 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,7 @@ "mui-tel-input": "^7.0.0", "notistack": "^3.0.1", "openweathermap-ts": "^1.2.10", - "protobuf-ts": "git+https://gitlab+deploy-token-50627:hv8mB4WkyvtjBpJKU1rN@gitlab.com/brandx/protobuf-ts.git#i2c_detect", + "protobuf-ts": "git+https://gitlab+deploy-token-50627:hv8mB4WkyvtjBpJKU1rN@gitlab.com/brandx/protobuf-ts.git#onewire_detect", "query-string": "^9.2.1", "react": "^18.3.1", "react-beautiful-dnd": "^13.1.1", diff --git a/src/device/DeviceWizard.tsx b/src/device/DeviceWizard.tsx index 32387eb..6c8f361 100644 --- a/src/device/DeviceWizard.tsx +++ b/src/device/DeviceWizard.tsx @@ -141,6 +141,28 @@ export default function DeviceWizard(props: Props) { )} + {selectedPort && + // selectedPort.addressType === quack.AddressType.ADDRESS_TYPE_CONFIGURABLE_PIN_ARRAY && + // device.featureSupported("detectOneWire") && + selectedPort.autoDetectable && ( + + { + setButtonClicked(true) + console.log(selectedPort) + deviceAPI.detectOneWire(device.id(), selectedPort.address) + .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 index 0381281..530ecb9 100644 --- a/src/device/autoDetect/DeviceScannedComponents.tsx +++ b/src/device/autoDetect/DeviceScannedComponents.tsx @@ -31,7 +31,8 @@ export default function DeviceScannedComponents(props: Props){ const compAPI = useComponentAPI(); const deviceAPI = useDeviceAPI() const [scannedI2C, setScannedI2C] = useState() //the unmodified scan of addresses - const [validCompAddresses, setValidComponentAddresses] = useState([]) //the filtered array of address data + const [scannedOneWire, setScannedOneWire] = useState([]) + const [validI2CCompAddresses, setValidI2CComponentAddresses] = useState([]) //the filtered array of address data const [components, setComponents] = useState([]) const [steps, setSteps] = useState([]); const { error, success } = useSnackbar(); @@ -40,8 +41,8 @@ export default function DeviceScannedComponents(props: Props){ const [openDialog, setOpenDialog] = useState(false); useEffect(()=>{ - //console.log(scannedComponents) if (scannedComponents.i2c) setScannedI2C(scannedComponents.i2c) + if (scannedComponents.oneWire) setScannedOneWire(scannedComponents.oneWire) //makes the array empty for testing // if (scannedComponents.i2c) { // let clone = cloneDeep(scannedComponents.i2c) @@ -76,7 +77,7 @@ export default function DeviceScannedComponents(props: Props){ } }) } - setValidComponentAddresses(valid) + setValidI2CComponentAddresses(valid) },[scannedI2C]) const stepper = () => { @@ -225,7 +226,7 @@ export default function DeviceScannedComponents(props: Props){ - {validCompAddresses.length > 0 ? validCompAddresses.map((addr, index) => { + {validI2CCompAddresses.length > 0 ? validI2CCompAddresses.map((addr, index) => { return ( ()}/> ) @@ -242,6 +243,23 @@ export default function DeviceScannedComponents(props: Props){ } } + {scannedOneWire.length > 0 && + + + + Pin Port Sensors + + + + {scannedOneWire.map(scan => { + return( + + + + ) + })} + + } diff --git a/src/device/autoDetect/ScannedOneWirePort.tsx b/src/device/autoDetect/ScannedOneWirePort.tsx new file mode 100644 index 0000000..f391dd3 --- /dev/null +++ b/src/device/autoDetect/ScannedOneWirePort.tsx @@ -0,0 +1,7 @@ +import React from "react" + +export default function ScannedOneWirePort(){ + return ( + + ) +} \ No newline at end of file diff --git a/src/models/Device.ts b/src/models/Device.ts index 0aec35a..29f06ef 100644 --- a/src/models/Device.ts +++ b/src/models/Device.ts @@ -48,6 +48,21 @@ const featureVersions: Map = new Map([ v2CellBlue: "2.1.7", v2EthBlue: "2.1.7" } + ],[ + "detectOneWire", + { + photon: "N/A", + electron: "N/A", + v2Wifi: "N/A", + v2Cell: "N/A", + v2WifiS3: "N/A", + v2CellS3: "N/A", + v2CellBlack: "2.1.8", + v2CellGreen: "N/A", + v2WifiBlue: "2.1.8", + v2CellBlue: "2.1.8", + v2EthBlue: "2.1.8" + } ] ]); export class Device { diff --git a/src/pages/Device.tsx b/src/pages/Device.tsx index 4d7d41f..e9012ee 100644 --- a/src/pages/Device.tsx +++ b/src/pages/Device.tsx @@ -1,4 +1,4 @@ -import { Button, Card, Divider, List, ListItem, Typography } from "@mui/material"; +import { Box, 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"; @@ -169,7 +169,8 @@ export default function DevicePage() { const loadPortScan = () => { deviceAPI.listFoundComponents(parseInt(deviceID)) .then(resp => { - if (resp.data.foundComponents?.i2c){ + console.log(resp.data) + if (resp.data.foundComponents){ setScannedAddresses(resp.data.foundComponents ?? undefined) } }) @@ -430,8 +431,8 @@ export default function DevicePage() { refreshCallback={loadDevice} /> - {scannedAddresses && - + {(scannedAddresses?.i2c || scannedAddresses?.oneWire) && + Promise>; getMulti: (ids: number[] | string[], otherTeam?: string) => Promise>; detectI2C: (id: number, otherTeam?: string) => Promise>; + detectOneWire: (id: number, port: 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; @@ -962,6 +963,19 @@ export default function DeviceProvider(props: PropsWithChildren) { }) } + const detectOneWire = (id: number, port: number, otherTeam?: string) => { + let url = "/devices/" + id + "/detectOneWire?port=" + port; + const view = otherTeam ? otherTeam : as + if(view) url = url + "?as=" + view + return new Promise>((resolve, reject) => { + put(pondURL(url)).then(resp => { + return resolve(resp) + }).catch(err => { + return reject(err) + }) + }) + } + const listFoundComponents = (id: number, otherTeam?: string) => { let url = "/devices/" + id + "/listScannedComponents"; const view = otherTeam ? otherTeam : as @@ -1035,6 +1049,7 @@ export default function DeviceProvider(props: PropsWithChildren) { updateComponentPreferences, listDeviceComponentPreferences, detectI2C, + detectOneWire, listFoundComponents, removeFoundComponents }}> From 8f601b360e26f14eb5aa97ebc9b4b062619d9ee8 Mon Sep 17 00:00:00 2001 From: csawatzky Date: Mon, 3 Nov 2025 09:22:47 -0600 Subject: [PATCH 02/11] put in all the data that will be displayed --- package-lock.json | 2 +- .../autoDetect/DeviceScannedComponents.tsx | 21 +++++++-- .../autoDetect/OneWire/PortComponent.tsx | 47 +++++++++++++++++++ .../autoDetect/OneWire/ScannedOneWirePort.tsx | 31 ++++++++++++ src/device/autoDetect/ScannedOneWirePort.tsx | 7 --- src/pages/Device.tsx | 2 +- 6 files changed, 97 insertions(+), 13 deletions(-) create mode 100644 src/device/autoDetect/OneWire/PortComponent.tsx create mode 100644 src/device/autoDetect/OneWire/ScannedOneWirePort.tsx delete mode 100644 src/device/autoDetect/ScannedOneWirePort.tsx diff --git a/package-lock.json b/package-lock.json index 8bf5f65..04f2a51 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10953,7 +10953,7 @@ }, "node_modules/protobuf-ts": { "version": "1.0.0", - "resolved": "git+https://gitlab+deploy-token-50627:hv8mB4WkyvtjBpJKU1rN@gitlab.com/brandx/protobuf-ts.git#aab2a77a75ca78e22d69d4a44e1c900bbac41bcf", + "resolved": "git+https://gitlab+deploy-token-50627:hv8mB4WkyvtjBpJKU1rN@gitlab.com/brandx/protobuf-ts.git#53e313b9d0a3b0c081be17f9a599abed80259c6c", "dependencies": { "protobufjs": "^6.8.8" } diff --git a/src/device/autoDetect/DeviceScannedComponents.tsx b/src/device/autoDetect/DeviceScannedComponents.tsx index 530ecb9..18ea15f 100644 --- a/src/device/autoDetect/DeviceScannedComponents.tsx +++ b/src/device/autoDetect/DeviceScannedComponents.tsx @@ -7,9 +7,11 @@ import { useEffect, useState } from "react"; import ScannedI2C from "./ScannedI2C"; import ComponentForm from "component/ComponentForm"; import { Component, Device } from "models"; -import { DeviceAvailabilityMap, OffsetAvailabilityMap } from "pbHelpers/DeviceAvailability"; +import { DeviceAvailabilityMap, FindAvailablePositions, OffsetAvailabilityMap } from "pbHelpers/DeviceAvailability"; import ResponsiveDialog from "common/ResponsiveDialog"; import { useComponentAPI, useDeviceAPI, useSnackbar } from "hooks"; +import { ConfigurablePin } from "pbHelpers/AddressTypes"; +import ScannedOneWirePort from "./OneWire/ScannedOneWirePort"; interface Props { scannedComponents: pond.ComponentAddressMap @@ -251,10 +253,21 @@ export default function DeviceScannedComponents(props: Props){ - {scannedOneWire.map(scan => { + {scannedOneWire.map((scan,i) => { + let map = FindAvailablePositions([], device.settings.product).availability.get(quack.AddressType.ADDRESS_TYPE_CONFIGURABLE_PIN_ARRAY) + let portAddress = scan.settings?.oneWireData?.port + let portLabel = "" + + map?.forEach(entry => { + let pin = entry as ConfigurablePin + if (pin.address && pin.address === portAddress) { + portLabel = pin.label + } + }) return( - - + + Port: {portLabel} + ) })} diff --git a/src/device/autoDetect/OneWire/PortComponent.tsx b/src/device/autoDetect/OneWire/PortComponent.tsx new file mode 100644 index 0000000..c92dfac --- /dev/null +++ b/src/device/autoDetect/OneWire/PortComponent.tsx @@ -0,0 +1,47 @@ +import { Box, MenuItem, TextField } from "@mui/material" +import { getFriendlyName, getSubtypes, Subtype } from "pbHelpers/ComponentType" +import { quack } from "protobuf-ts/quack" +import React, { useEffect, useState } from "react" + +interface Props { + compData: quack.OneWireComponentData +} + +export default function PortComponent(props: Props){ + const {compData} = props + const [selectedSubtype, setSelectedSubtype] = useState(-1) + + useEffect(()=>{ + setSelectedSubtype(compData.subtype) + },[compData]) + + const subtypeSelector = (compData: quack.OneWireComponentData) => { + let validSubtypes: Subtype[] = [] + getSubtypes(compData.type).forEach(option => { + if(compData.subtype === option.key || compData.subtype === 0){ + validSubtypes.push(option) + } + }) + return ( + + Select the Component Subtype + {validSubtypes.map((s, i) => ( + {s.friendlyName} + ))} + + ) + } + + return ( + + + {getFriendlyName(compData.type)} + Cable ID: {compData.cableId} + Number of nodes: {compData.nodeCount} + {subtypeSelector(compData)} + + + ) +} \ No newline at end of file diff --git a/src/device/autoDetect/OneWire/ScannedOneWirePort.tsx b/src/device/autoDetect/OneWire/ScannedOneWirePort.tsx new file mode 100644 index 0000000..a4f3e11 --- /dev/null +++ b/src/device/autoDetect/OneWire/ScannedOneWirePort.tsx @@ -0,0 +1,31 @@ +import { Box, MenuItem, TextField } from "@mui/material" +import { extension, getFriendlyName, getSubtypes, Subtype } from "pbHelpers/ComponentType" +import { pond } from "protobuf-ts/pond" +import { quack } from "protobuf-ts/quack" +import React, { useEffect, useState } from "react" +import PortComponent from "./PortComponent" + +interface Props { + scan: pond.DetectOneWire +} + +export default function ScannedOneWirePort(props: Props){ + const {scan} = props + const [portComponents, setPortComponents] = useState([]) + + useEffect(()=>{ + setPortComponents(scan.settings?.oneWireData?.components ?? []) + },[scan]) + + return ( + + {portComponents.map((compData, i) => { + // let ext = extension(compData.type, compData.subtype) + // console.log(ext) + return ( + + ) + })} + + ) +} \ No newline at end of file diff --git a/src/device/autoDetect/ScannedOneWirePort.tsx b/src/device/autoDetect/ScannedOneWirePort.tsx deleted file mode 100644 index f391dd3..0000000 --- a/src/device/autoDetect/ScannedOneWirePort.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import React from "react" - -export default function ScannedOneWirePort(){ - return ( - - ) -} \ No newline at end of file diff --git a/src/pages/Device.tsx b/src/pages/Device.tsx index e9012ee..ec3443d 100644 --- a/src/pages/Device.tsx +++ b/src/pages/Device.tsx @@ -171,7 +171,7 @@ export default function DevicePage() { .then(resp => { console.log(resp.data) if (resp.data.foundComponents){ - setScannedAddresses(resp.data.foundComponents ?? undefined) + setScannedAddresses(pond.ListFoundComponentsResponse.fromObject(resp.data).foundComponents ?? undefined) } }) .catch(err => { From 65cb7acbab85037fc39d8e016071dfc082d46faa Mon Sep 17 00:00:00 2001 From: csawatzky Date: Mon, 3 Nov 2025 13:23:02 -0600 Subject: [PATCH 03/11] finished the functionality for adding components from the scan --- .../autoDetect/DeviceScannedComponents.tsx | 13 ++-- .../autoDetect/OneWire/PortComponent.tsx | 62 +++++++++++++++---- .../autoDetect/OneWire/ScannedOneWirePort.tsx | 31 ++++++++-- src/pbHelpers/ComponentType.tsx | 1 + .../ComponentTypes/CapacitorCable.ts | 1 + src/pbHelpers/ComponentTypes/GrainCable.ts | 1 + src/pbHelpers/ComponentTypes/PressureCable.ts | 1 + 7 files changed, 90 insertions(+), 20 deletions(-) diff --git a/src/device/autoDetect/DeviceScannedComponents.tsx b/src/device/autoDetect/DeviceScannedComponents.tsx index 18ea15f..e1fc020 100644 --- a/src/device/autoDetect/DeviceScannedComponents.tsx +++ b/src/device/autoDetect/DeviceScannedComponents.tsx @@ -203,6 +203,7 @@ export default function DeviceScannedComponents(props: Props){ }) }) } + console.log(cloneList) setComponents(cloneList) } @@ -251,7 +252,6 @@ export default function DeviceScannedComponents(props: Props){ Pin Port Sensors - {scannedOneWire.map((scan,i) => { let map = FindAvailablePositions([], device.settings.product).availability.get(quack.AddressType.ADDRESS_TYPE_CONFIGURABLE_PIN_ARRAY) @@ -265,9 +265,14 @@ export default function DeviceScannedComponents(props: Props){ } }) return( - - Port: {portLabel} - + + + Port: {portLabel} + + + ) })} diff --git a/src/device/autoDetect/OneWire/PortComponent.tsx b/src/device/autoDetect/OneWire/PortComponent.tsx index c92dfac..ee2ab3f 100644 --- a/src/device/autoDetect/OneWire/PortComponent.tsx +++ b/src/device/autoDetect/OneWire/PortComponent.tsx @@ -1,46 +1,84 @@ -import { Box, MenuItem, TextField } from "@mui/material" +import { Box, Checkbox, MenuItem, TextField, Tooltip } from "@mui/material" import { getFriendlyName, getSubtypes, Subtype } from "pbHelpers/ComponentType" import { quack } from "protobuf-ts/quack" import React, { useEffect, useState } from "react" interface Props { compData: quack.OneWireComponentData + componentSelect: (selected: boolean, componentData: quack.OneWireComponentData) => void } export default function PortComponent(props: Props){ - const {compData} = props - const [selectedSubtype, setSelectedSubtype] = useState(-1) + const {compData, componentSelect} = props + // const [selectedSubtype, setSelectedSubtype] = useState(0) + const [subtypeVal, setSubtypeVal] = useState("none")//note that this is the friendly name and not the key or the value because it needs to be different from the other alias options + const [subtypeMap, setSubtypeMap] = useState>(new Map()) + const [subtypeOptions, setSubtypeOptions] = useState([]) + const [added, setAdded] = useState(false) useEffect(()=>{ - setSelectedSubtype(compData.subtype) - },[compData]) - - const subtypeSelector = (compData: quack.OneWireComponentData) => { + // setSelectedSubtype(compData.subtype) let validSubtypes: Subtype[] = [] + let subMap: Map = new Map() + let subVal: string = "none" getSubtypes(compData.type).forEach(option => { if(compData.subtype === option.key || compData.subtype === 0){ validSubtypes.push(option) + if(subVal === "none"){ + subVal = option.friendlyName + } } + subMap.set(option.friendlyName, option.key) }) + setSubtypeOptions(validSubtypes) + setSubtypeMap(subMap) + setSubtypeVal(subVal) + },[compData]) + + const subtypeSelector = () => { return ( { + setSubtypeVal(event.target.value) + // setSelectedSubtype(subtypeMap.get(event.target.value) ?? 0) + compData.subtype = subtypeMap.get(event.target.value) ?? 0 + }} select> - Select the Component Subtype - {validSubtypes.map((s, i) => ( - {s.friendlyName} + Select the Component Subtype + {subtypeOptions.map((s, i) => ( + {s.friendlyName} ))} ) } + const selectCompCheckbox = () => { + return ( + { + setAdded(checked) + componentSelect(checked, compData) + }} + /> + } + /> + ) + } + return ( {getFriendlyName(compData.type)} Cable ID: {compData.cableId} Number of nodes: {compData.nodeCount} - {subtypeSelector(compData)} + {subtypeOptions.length < 2 ? subtypeVal : subtypeSelector()} + {selectCompCheckbox()} ) diff --git a/src/device/autoDetect/OneWire/ScannedOneWirePort.tsx b/src/device/autoDetect/OneWire/ScannedOneWirePort.tsx index a4f3e11..4fd99d8 100644 --- a/src/device/autoDetect/OneWire/ScannedOneWirePort.tsx +++ b/src/device/autoDetect/OneWire/ScannedOneWirePort.tsx @@ -4,26 +4,49 @@ import { pond } from "protobuf-ts/pond" import { quack } from "protobuf-ts/quack" import React, { useEffect, useState } from "react" import PortComponent from "./PortComponent" +import { Component } from "models" interface Props { scan: pond.DetectOneWire + componentSelectionCallback: (newComponents: Component[], checked: boolean) => void } export default function ScannedOneWirePort(props: Props){ - const {scan} = props + const {scan, componentSelectionCallback} = props const [portComponents, setPortComponents] = useState([]) useEffect(()=>{ setPortComponents(scan.settings?.oneWireData?.components ?? []) },[scan]) + const componentSelected = (checked: boolean, componentData: quack.OneWireComponentData) => { + let newComponents: Component[] = [] + //use the component data to create a new Component + //build a component with given information and defaults for the rest + let primaryComponent = Component.create() + primaryComponent.settings.type = componentData.type + primaryComponent.settings.subtype = componentData.subtype + primaryComponent.settings.address = scan.settings?.oneWireData?.port ?? 0 + primaryComponent.settings.addressType = quack.AddressType.ADDRESS_TYPE_CONFIGURABLE_PIN_ARRAY + primaryComponent.settings.name = getFriendlyName(componentData.type, componentData.subtype) + + //need to check if the component is chainable, meaning the address type will reflect the cable id + let ext = extension(componentData.type, componentData.subtype) + if(ext.isChainable){ + primaryComponent.settings.addressType = componentData.cableId + 8 + } + newComponents.push(primaryComponent) + + componentSelectionCallback(newComponents, checked) + } + return ( {portComponents.map((compData, i) => { - // let ext = extension(compData.type, compData.subtype) - // console.log(ext) return ( - + { + componentSelected(checked, component) + }}/> ) })} diff --git a/src/pbHelpers/ComponentType.tsx b/src/pbHelpers/ComponentType.tsx index 60f14cd..03be638 100644 --- a/src/pbHelpers/ComponentType.tsx +++ b/src/pbHelpers/ComponentType.tsx @@ -168,6 +168,7 @@ export interface ComponentTypeExtension { //if the map does not exist then just use the array from the device availability, //if the map does exist filter the availability after claims to find matching address between them and use that subtypeI2CMap?: Map + isChainable?: boolean } export interface Summary { diff --git a/src/pbHelpers/ComponentTypes/CapacitorCable.ts b/src/pbHelpers/ComponentTypes/CapacitorCable.ts index cc56e27..8843952 100644 --- a/src/pbHelpers/ComponentTypes/CapacitorCable.ts +++ b/src/pbHelpers/ComponentTypes/CapacitorCable.ts @@ -68,6 +68,7 @@ export function CapacitorCable(subtype: number = 0): ComponentTypeExtension { isSource: true, isArray: true, isCalibratable: false, + isChainable: true, addressTypes: addressTypes, interactionResultTypes: [], states: [], diff --git a/src/pbHelpers/ComponentTypes/GrainCable.ts b/src/pbHelpers/ComponentTypes/GrainCable.ts index c715611..bacc514 100644 --- a/src/pbHelpers/ComponentTypes/GrainCable.ts +++ b/src/pbHelpers/ComponentTypes/GrainCable.ts @@ -176,6 +176,7 @@ export function GrainCable(subtype: number = 0): ComponentTypeExtension { isSource: true, isArray: true, isCalibratable: false, + isChainable: true, addressTypes: [quack.AddressType.ADDRESS_TYPE_CONFIGURABLE_PIN_ARRAY, quack.AddressType.ADDRESS_TYPE_I2C], interactionResultTypes: [], states: [], diff --git a/src/pbHelpers/ComponentTypes/PressureCable.ts b/src/pbHelpers/ComponentTypes/PressureCable.ts index f03cc9e..3a22362 100644 --- a/src/pbHelpers/ComponentTypes/PressureCable.ts +++ b/src/pbHelpers/ComponentTypes/PressureCable.ts @@ -64,6 +64,7 @@ export function PressureCable(subtype: number = 0): ComponentTypeExtension { isArray: true, hasFan: true, isCalibratable: false, + isChainable: true, addressTypes: [quack.AddressType.ADDRESS_TYPE_CONFIGURABLE_PIN_ARRAY], interactionResultTypes: [], states: [], From 487c8617e4fe2ba2d514a2f76c3264a18cfb8600 Mon Sep 17 00:00:00 2001 From: csawatzky Date: Mon, 3 Nov 2025 16:41:26 -0600 Subject: [PATCH 04/11] first iteration of basic layout --- src/device/DeviceWizard.tsx | 4 +- .../autoDetect/DeviceScannedComponents.tsx | 10 +-- .../autoDetect/OneWire/PortComponent.tsx | 89 ++++++++++++++++--- .../autoDetect/OneWire/ScannedOneWirePort.tsx | 9 +- src/pages/Device.tsx | 11 ++- 5 files changed, 100 insertions(+), 23 deletions(-) diff --git a/src/device/DeviceWizard.tsx b/src/device/DeviceWizard.tsx index 6c8f361..cf0a061 100644 --- a/src/device/DeviceWizard.tsx +++ b/src/device/DeviceWizard.tsx @@ -142,8 +142,8 @@ export default function DeviceWizard(props: Props) { )} {selectedPort && - // selectedPort.addressType === quack.AddressType.ADDRESS_TYPE_CONFIGURABLE_PIN_ARRAY && - // device.featureSupported("detectOneWire") && + selectedPort.addressType === quack.AddressType.ADDRESS_TYPE_CONFIGURABLE_PIN_ARRAY && + device.featureSupported("detectOneWire") && selectedPort.autoDetectable && ( {scannedI2C !== undefined && - + I2C Sensors @@ -244,10 +244,10 @@ export default function DeviceScannedComponents(props: Props){ } - + } {scannedOneWire.length > 0 && - + Pin Port Sensors @@ -265,8 +265,8 @@ export default function DeviceScannedComponents(props: Props){ } }) return( - - + + Port: {portLabel} + {validI2CCompAddresses.length > 0 ? validI2CCompAddresses.map((addr, index) => { return ( @@ -269,7 +269,7 @@ export default function DeviceScannedComponents(props: Props){ Port: {portLabel} diff --git a/src/providers/pond/deviceAPI.tsx b/src/providers/pond/deviceAPI.tsx index f967774..56a0c0f 100644 --- a/src/providers/pond/deviceAPI.tsx +++ b/src/providers/pond/deviceAPI.tsx @@ -149,7 +149,7 @@ export interface IDeviceAPIContext { keys?: string[], types?: string[] ) => Promise; - removeFoundComponents: (id: number, key: string, otherTeam?: string) => Promise>; + removeFoundComponents: (id: number, key: string, type: pond.ObjectType, otherTeam?: string) => Promise>; } export const DeviceAPIContext = createContext({} as IDeviceAPIContext); @@ -989,7 +989,7 @@ export default function DeviceProvider(props: PropsWithChildren) { }) } - const removeFoundComponents = (id: number, key: string, otherTeam?: string) => { + const removeFoundComponents = (id: number, key: string, type: pond.ObjectType, otherTeam?: string) => { let url = "/devices/" + id + "/removeFoundComponents/" + key; const view = otherTeam ? otherTeam : as if(view) url = url + "?as=" + view From 8dcc0405581c9d359a5be695bbc8a88df39b6ca9 Mon Sep 17 00:00:00 2001 From: csawatzky Date: Tue, 4 Nov 2025 12:28:21 -0600 Subject: [PATCH 06/11] fixing the url for the api call --- src/providers/pond/deviceAPI.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/providers/pond/deviceAPI.tsx b/src/providers/pond/deviceAPI.tsx index 56a0c0f..391caf7 100644 --- a/src/providers/pond/deviceAPI.tsx +++ b/src/providers/pond/deviceAPI.tsx @@ -990,9 +990,9 @@ export default function DeviceProvider(props: PropsWithChildren) { } const removeFoundComponents = (id: number, key: string, type: pond.ObjectType, otherTeam?: string) => { - let url = "/devices/" + id + "/removeFoundComponents/" + key; + let url = "/devices/" + id + "/removeFoundComponents/" + key + "?type=" + type; const view = otherTeam ? otherTeam : as - if(view) url = url + "?as=" + view + if(view) url = url + "&as=" + view return new Promise>((resolve, reject) => { del(pondURL(url)).then(resp => { return resolve(resp) From efb3c9eb59d5413de77f7b366dc95bbd6a9fa91b Mon Sep 17 00:00:00 2001 From: csawatzky Date: Tue, 4 Nov 2025 12:29:08 -0600 Subject: [PATCH 07/11] use scanType instead of type --- src/providers/pond/deviceAPI.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/providers/pond/deviceAPI.tsx b/src/providers/pond/deviceAPI.tsx index 391caf7..4a90b85 100644 --- a/src/providers/pond/deviceAPI.tsx +++ b/src/providers/pond/deviceAPI.tsx @@ -990,7 +990,7 @@ export default function DeviceProvider(props: PropsWithChildren) { } const removeFoundComponents = (id: number, key: string, type: pond.ObjectType, otherTeam?: string) => { - let url = "/devices/" + id + "/removeFoundComponents/" + key + "?type=" + type; + let url = "/devices/" + id + "/removeFoundComponents/" + key + "?scanType=" + type; const view = otherTeam ? otherTeam : as if(view) url = url + "&as=" + view return new Promise>((resolve, reject) => { From 14126fd7c5e60b41562d5cfbe57ada0a00f9138f Mon Sep 17 00:00:00 2001 From: csawatzky Date: Tue, 4 Nov 2025 14:16:40 -0600 Subject: [PATCH 08/11] adding button for clearing all of the scans, including ones that were replaced by new scans --- package-lock.json | 2 +- .../autoDetect/DeviceScannedComponents.tsx | 28 +++++++++++++++++++ src/pages/Device.tsx | 2 +- src/providers/pond/deviceAPI.tsx | 19 +++++++++++-- 4 files changed, 47 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index f60c304..1bef6b0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10953,7 +10953,7 @@ }, "node_modules/protobuf-ts": { "version": "1.0.0", - "resolved": "git+https://gitlab+deploy-token-50627:hv8mB4WkyvtjBpJKU1rN@gitlab.com/brandx/protobuf-ts.git#9dcc83dddad31d4a4d8a002ec31475cbb83f0689", + "resolved": "git+https://gitlab+deploy-token-50627:hv8mB4WkyvtjBpJKU1rN@gitlab.com/brandx/protobuf-ts.git#910e6c4dd322a52a7f0c82d5bde650d8ccfff548", "dependencies": { "protobufjs": "^6.8.8" } diff --git a/src/device/autoDetect/DeviceScannedComponents.tsx b/src/device/autoDetect/DeviceScannedComponents.tsx index 3448b86..cda95ae 100644 --- a/src/device/autoDetect/DeviceScannedComponents.tsx +++ b/src/device/autoDetect/DeviceScannedComponents.tsx @@ -41,6 +41,7 @@ export default function DeviceScannedComponents(props: Props){ const [currentStep, setCurrentStep] = useState(0) const [settingsValid, setSettingsValid] = useState(false); const [openDialog, setOpenDialog] = useState(false); + const [clearOpen, setClearOpen] = useState(false); useEffect(()=>{ if (scannedComponents.i2c) setScannedI2C(scannedComponents.i2c) @@ -216,11 +217,38 @@ export default function DeviceScannedComponents(props: Props){ }) } + const removeAllScans = () => { + deviceAPI.removeAllFoundComponents(device.settings.deviceId) + .then(resp => { + console.log("Cleared all scans") + }).catch(err => { + console.log("There was a problem clearing scans") + }) + } + + const clearWarning = () => { + return ( + {setClearOpen(false)}}> + Clear All Scans + This action will clear all scans for this device. + + + + + + ) + } + return ( + {clearWarning()} + + Sensor Scan + + {scannedI2C !== undefined && diff --git a/src/pages/Device.tsx b/src/pages/Device.tsx index 0a4e89a..7344659 100644 --- a/src/pages/Device.tsx +++ b/src/pages/Device.tsx @@ -170,7 +170,7 @@ export default function DevicePage() { deviceAPI.listFoundComponents(parseInt(deviceID)) .then(resp => { console.log(resp.data) - if (resp.data.foundComponents){ + if (resp.data.foundComponents?.i2c || resp.data.foundComponents?.oneWire){ setScannedAddresses(pond.ListFoundComponentsResponse.fromObject(resp.data).foundComponents ?? undefined) } }) diff --git a/src/providers/pond/deviceAPI.tsx b/src/providers/pond/deviceAPI.tsx index 4a90b85..241781b 100644 --- a/src/providers/pond/deviceAPI.tsx +++ b/src/providers/pond/deviceAPI.tsx @@ -149,6 +149,7 @@ export interface IDeviceAPIContext { keys?: string[], types?: string[] ) => Promise; + removeAllFoundComponents: (id: number,otherTeam?: string) => Promise>; removeFoundComponents: (id: number, key: string, type: pond.ObjectType, otherTeam?: string) => Promise>; } @@ -990,7 +991,7 @@ export default function DeviceProvider(props: PropsWithChildren) { } const removeFoundComponents = (id: number, key: string, type: pond.ObjectType, otherTeam?: string) => { - let url = "/devices/" + id + "/removeFoundComponents/" + key + "?scanType=" + type; + let url = "/devices/" + id + "/removeFoundComponents/" + key + "?scanType=" + type; const view = otherTeam ? otherTeam : as if(view) url = url + "&as=" + view return new Promise>((resolve, reject) => { @@ -1002,6 +1003,19 @@ export default function DeviceProvider(props: PropsWithChildren) { }) } + const removeAllFoundComponents = (id: number, otherTeam?: string) => { + let url = "/devices/" + id + "/removeAllFoundComponents"; + const view = otherTeam ? otherTeam : as + if(view) url = url + "?as=" + view + return new Promise>((resolve, reject) => { + del(pondURL(url)).then(resp => { + return resolve(resp) + }).catch(err => { + return reject(err) + }) + }) + } + return ( ) { detectI2C, detectOneWire, listFoundComponents, - removeFoundComponents + removeFoundComponents, + removeAllFoundComponents }}> {children} From 4e60d9bcdb2044078e1254b9a0b1bc46b14dbce4 Mon Sep 17 00:00:00 2001 From: csawatzky Date: Tue, 4 Nov 2025 15:13:46 -0600 Subject: [PATCH 09/11] closing the dialog and using the refresh callback --- src/device/autoDetect/DeviceScannedComponents.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/device/autoDetect/DeviceScannedComponents.tsx b/src/device/autoDetect/DeviceScannedComponents.tsx index cda95ae..2be89a9 100644 --- a/src/device/autoDetect/DeviceScannedComponents.tsx +++ b/src/device/autoDetect/DeviceScannedComponents.tsx @@ -221,6 +221,7 @@ export default function DeviceScannedComponents(props: Props){ deviceAPI.removeAllFoundComponents(device.settings.deviceId) .then(resp => { console.log("Cleared all scans") + refreshCallback() }).catch(err => { console.log("There was a problem clearing scans") }) @@ -233,7 +234,10 @@ export default function DeviceScannedComponents(props: Props){ This action will clear all scans for this device. - + ) From fa85c3b6aba3980d4b3ef3daa8ad10fb7779a979 Mon Sep 17 00:00:00 2001 From: csawatzky Date: Thu, 13 Nov 2025 11:35:31 -0600 Subject: [PATCH 10/11] increase the feature version --- src/models/Device.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/models/Device.ts b/src/models/Device.ts index 29f06ef..de919e4 100644 --- a/src/models/Device.ts +++ b/src/models/Device.ts @@ -57,11 +57,11 @@ const featureVersions: Map = new Map([ v2Cell: "N/A", v2WifiS3: "N/A", v2CellS3: "N/A", - v2CellBlack: "2.1.8", + v2CellBlack: "2.1.9", v2CellGreen: "N/A", - v2WifiBlue: "2.1.8", - v2CellBlue: "2.1.8", - v2EthBlue: "2.1.8" + v2WifiBlue: "2.1.9", + v2CellBlue: "2.1.9", + v2EthBlue: "2.1.9" } ] ]); From 895554786830d40e6768a9b541d2106842aae7bd Mon Sep 17 00:00:00 2001 From: csawatzky Date: Thu, 20 Nov 2025 10:28:08 -0600 Subject: [PATCH 11/11] increasing the detect onewire to 10 since 9 is going to be for increasing the conditions on an interaction --- src/models/Device.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/models/Device.ts b/src/models/Device.ts index de919e4..0851041 100644 --- a/src/models/Device.ts +++ b/src/models/Device.ts @@ -57,11 +57,11 @@ const featureVersions: Map = new Map([ v2Cell: "N/A", v2WifiS3: "N/A", v2CellS3: "N/A", - v2CellBlack: "2.1.9", + v2CellBlack: "2.1.10", v2CellGreen: "N/A", - v2WifiBlue: "2.1.9", - v2CellBlue: "2.1.9", - v2EthBlue: "2.1.9" + v2WifiBlue: "2.1.10", + v2CellBlue: "2.1.10", + v2EthBlue: "2.1.10" } ] ]);