189 lines
7.6 KiB
TypeScript
189 lines
7.6 KiB
TypeScript
import { cloneDeep } from "lodash";
|
|
import { Component } from "models";
|
|
import { ConfigurablePin } from "pbHelpers/AddressTypes/ConfigurablePinArray";
|
|
import { GetProductAvailability } from "products/DeviceProduct";
|
|
import { pond } from "protobuf-ts/pond";
|
|
import { quack } from "protobuf-ts/quack";
|
|
import { or } from "utils/types";
|
|
import { FilterSubtypeI2C } from "./ComponentType";
|
|
|
|
export type ComponentAvailabilityMap = Map<quack.ComponentType, number[]>;
|
|
export type DevicePositions = number[] | ComponentAvailabilityMap | ConfigurablePin[];
|
|
export type DeviceAvailabilityMap = Map<quack.AddressType, DevicePositions>;
|
|
export type OffsetAvailabilityMap = Map<quack.AddressType, number[][]>;
|
|
|
|
const DefaultPinArray: ConfigurablePin[] = [
|
|
{ address: 1, label: "1" },
|
|
{ address: 2, label: "2" },
|
|
{ address: 4, label: "3" },
|
|
{ address: 8, label: "4" },
|
|
{ address: 16, label: "5" },
|
|
{ address: 32, label: "6" },
|
|
{ address: 64, label: "7" },
|
|
{ address: 128, label: "8" },
|
|
{ address: 256, label: "9" },
|
|
{ address: 512, label: "10" },
|
|
{ address: 1024, label: "11" },
|
|
{ address: 2048, label: "12" },
|
|
{ address: 4096, label: "13" },
|
|
{ address: 8192, label: "14" }
|
|
];
|
|
|
|
const OffsetArray: number[] = [0, 1, 2, 3, 4, 5, 6, 7];
|
|
|
|
const OffsetAvailability: OffsetAvailabilityMap = new Map<quack.AddressType, number[][]>([
|
|
[quack.AddressType.ADDRESS_TYPE_INVALID, Array(14).fill([])],
|
|
[quack.AddressType.ADDRESS_TYPE_CONFIGURABLE_PIN_ARRAY, Array(14).fill(OffsetArray)],
|
|
[quack.AddressType.ADDRESS_TYPE_I2C, Array(14).fill([0, 1])],
|
|
[quack.AddressType.ADDRESS_TYPE_DAC, Array(14).fill([0])],
|
|
[quack.AddressType.ADDRESS_TYPE_POWER, Array(14).fill([0])],
|
|
[quack.AddressType.ADDRESS_TYPE_GPS, Array(14).fill([0])],
|
|
[quack.AddressType.ADDRESS_TYPE_MODEM, Array(14).fill([0])],
|
|
[quack.AddressType.ADDRESS_TYPE_I2C_WITH_CHANNELS, Array(14).fill([0])],
|
|
[quack.AddressType.ADDRESS_TYPE_INCREMENTAL, Array(14).fill([0])]
|
|
]);
|
|
|
|
const DefaultAvailability: DeviceAvailabilityMap = new Map<quack.AddressType, DevicePositions>([
|
|
[quack.AddressType.ADDRESS_TYPE_INVALID, []],
|
|
[quack.AddressType.ADDRESS_TYPE_CONFIGURABLE_PIN_ARRAY, DefaultPinArray],
|
|
[
|
|
quack.AddressType.ADDRESS_TYPE_I2C,
|
|
//this will contain all the possible addresses for a component type, if subtypes use specific addresses add a filter to the type describer, see lidar.ts for an example
|
|
new Map<quack.ComponentType, number[]>([
|
|
[quack.ComponentType.COMPONENT_TYPE_PRESSURE, [0x18, 0x19, 0x1a]],
|
|
[quack.ComponentType.COMPONENT_TYPE_LIGHT, [0x29]],
|
|
[quack.ComponentType.COMPONENT_TYPE_CO2, [0x61]],
|
|
[quack.ComponentType.COMPONENT_TYPE_STEPPER_MOTOR, [0x14, 0x15, 0x16, 0x17]],
|
|
[quack.ComponentType.COMPONENT_TYPE_PH, [0x40]],
|
|
[quack.ComponentType.COMPONENT_TYPE_DHT, [0x40, 0x61]],
|
|
// [quack.ComponentType.COMPONENT_TYPE_VAPOUR_PRESSURE_DEFICIT, [0x40]], //component type deprecated?
|
|
[quack.ComponentType.COMPONENT_TYPE_AIR_QUALITY, [0x58]],
|
|
[quack.ComponentType.COMPONENT_TYPE_LIDAR, [0x62, 0x66, 0x10]],
|
|
[quack.ComponentType.COMPONENT_TYPE_CAPACITANCE, [0x50]],
|
|
[quack.ComponentType.COMPONENT_TYPE_CAPACITOR_CABLE, [0x50]],
|
|
[quack.ComponentType.COMPONENT_TYPE_SEN5X, [0x69]],
|
|
[quack.ComponentType.COMPONENT_TYPE_AIRFLOW, [0x6c]],
|
|
[quack.ComponentType.COMPONENT_TYPE_GRAIN_CABLE, [0x71]], // the address cables will use when they are plugged into the expander with V2 device only
|
|
[quack.ComponentType.COMPONENT_TYPE_DRAGER_GAS_DONGLE, [0x6d]],
|
|
[quack.ComponentType.COMPONENT_TYPE_TEMP_HUMIDITY, [0x44]]
|
|
])
|
|
],
|
|
[quack.AddressType.ADDRESS_TYPE_DAC, [0, 1]],
|
|
[quack.AddressType.ADDRESS_TYPE_POWER, [0]],
|
|
[quack.AddressType.ADDRESS_TYPE_GPS, [0]],
|
|
[quack.AddressType.ADDRESS_TYPE_MODEM, [0]],
|
|
[
|
|
quack.AddressType.ADDRESS_TYPE_I2C_WITH_CHANNELS, //this array needs to be built in the component types definition
|
|
[
|
|
(0x40 << 2) + 0,
|
|
(0x40 << 2) + 1,
|
|
(0x41 << 2) + 0,
|
|
(0x41 << 2) + 1,
|
|
(0x44 << 2) + 0,
|
|
(0x44 << 2) + 1,
|
|
(0x45 << 2) + 0,
|
|
(0x45 << 2) + 1
|
|
]
|
|
],
|
|
[quack.AddressType.ADDRESS_TYPE_INCREMENTAL, [1]],
|
|
[
|
|
quack.AddressType.ADDRESS_TYPE_SPI,
|
|
new Map<quack.ComponentType, number[]>([
|
|
[quack.ComponentType.COMPONENT_TYPE_VIBRATION_CHAIN, [0x0]]
|
|
])
|
|
]
|
|
]);
|
|
|
|
export class DeviceAvailability {
|
|
availability: DeviceAvailabilityMap;
|
|
offsetAvailability: OffsetAvailabilityMap;
|
|
constructor(product?: pond.DeviceProduct) {
|
|
const ProductAvailability = GetProductAvailability(product);
|
|
this.availability = ProductAvailability
|
|
? cloneDeep(ProductAvailability)
|
|
: cloneDeep(DefaultAvailability);
|
|
this.offsetAvailability = cloneDeep(OffsetAvailability);
|
|
}
|
|
|
|
ClaimAddress(
|
|
addressType: quack.AddressType,
|
|
componentType: quack.ComponentType,
|
|
address: number,
|
|
expansionLine?: number
|
|
) {
|
|
let offset = addressType - 8;
|
|
if (offset > 0) addressType = addressType - (7 + offset);
|
|
else offset = 0;
|
|
switch (addressType) {
|
|
case quack.AddressType.ADDRESS_TYPE_CONFIGURABLE_PIN_ARRAY:
|
|
//if (componentType === quack.ComponentType.COMPONENT_TYPE_GRAIN_CABLE) {
|
|
// break;
|
|
//}
|
|
let arrayPos = Math.log2(address);
|
|
let pinArray = cloneDeep(this.availability.get(addressType) as ConfigurablePin[]);
|
|
let offsetArray = this.offsetAvailability.get(addressType);
|
|
offsetArray = offsetArray ? offsetArray : [];
|
|
let newOffsetArray = cloneDeep(offsetArray);
|
|
newOffsetArray[arrayPos] = offsetArray[arrayPos]?.filter(o => o !== offset);
|
|
this.offsetAvailability.set(addressType, newOffsetArray);
|
|
if (offsetArray[arrayPos] ? offsetArray[arrayPos].length < 1 : false) {
|
|
let availablePins = pinArray.filter(p => p.address !== address);
|
|
this.availability.set(addressType, availablePins);
|
|
}
|
|
break;
|
|
case quack.AddressType.ADDRESS_TYPE_I2C:
|
|
case quack.AddressType.ADDRESS_TYPE_SPI:
|
|
if(expansionLine){
|
|
break;
|
|
}
|
|
let addressTypePositions = cloneDeep(
|
|
this.availability.get(addressType) as ComponentAvailabilityMap
|
|
);
|
|
let componentPositions = cloneDeep(addressTypePositions.get(componentType) || []);
|
|
componentPositions = componentPositions.filter(p => p !== address);
|
|
addressTypePositions.set(componentType, componentPositions);
|
|
this.availability.set(addressType, addressTypePositions);
|
|
break;
|
|
case quack.AddressType.ADDRESS_TYPE_INCREMENTAL:
|
|
let incrementalPositions = cloneDeep(this.availability.get(addressType) as number[]);
|
|
if (address >= incrementalPositions[0]) {
|
|
incrementalPositions[0] = address + 1;
|
|
}
|
|
this.availability.set(addressType, incrementalPositions);
|
|
break;
|
|
default:
|
|
let positions = cloneDeep(this.availability.get(addressType) as number[]);
|
|
if (positions) {
|
|
positions = positions.filter(p => p !== address);
|
|
this.availability.set(addressType, positions);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
GetAvailability() {
|
|
return this.availability;
|
|
}
|
|
|
|
GetOffsetAvailability() {
|
|
return this.offsetAvailability;
|
|
}
|
|
}
|
|
|
|
export function FindAvailablePositions(
|
|
components: Component[],
|
|
product?: pond.DeviceProduct
|
|
): DeviceAvailability {
|
|
const available = new DeviceAvailability(product);
|
|
components.forEach((component: Component) => {
|
|
if (component.settings.addressType) {
|
|
available.ClaimAddress(
|
|
component.settings.addressType,
|
|
component.settings.type,
|
|
or(component.settings.address, 0),
|
|
component.settings.expansionLine
|
|
);
|
|
}
|
|
});
|
|
return available;
|
|
}
|