280 lines
8.6 KiB
TypeScript
280 lines
8.6 KiB
TypeScript
import { pond } from "protobuf-ts/pond";
|
|
import { or } from "utils/types";
|
|
import { cloneDeep } from "lodash";
|
|
import { MarkerData } from "maps/mapMarkers/Markers";
|
|
|
|
interface FeatureVersionByPlatform {
|
|
photon: string;
|
|
electron: string;
|
|
v2Wifi: string;
|
|
v2Cell: string;
|
|
v2WifiS3: string;
|
|
v2CellS3: string;
|
|
v2CellBlack: string;
|
|
v2CellGreen: string;
|
|
v2WifiBlue: string;
|
|
v2CellBlue: string;
|
|
v2EthBlue: string;
|
|
}
|
|
|
|
const featureVersions: Map<string, FeatureVersionByPlatform> = new Map([
|
|
[
|
|
"individualCalibrations",
|
|
{
|
|
photon: "1.19.64",
|
|
electron: "1.19.64",
|
|
v2Cell: "2.0.44",
|
|
v2Wifi: "2.0.44",
|
|
v2WifiS3: "2.0.44",
|
|
v2CellS3: "2.0.44",
|
|
v2CellBlack: "2.0.44",
|
|
v2CellGreen: "2.0.44",
|
|
v2WifiBlue: "2.0.44",
|
|
v2CellBlue: "2.0.44",
|
|
v2EthBlue: "2.0.44"
|
|
}
|
|
],[
|
|
"reverseNodes",
|
|
{
|
|
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"
|
|
}
|
|
],
|
|
[
|
|
"detectI2C",
|
|
{
|
|
photon: "N/A",
|
|
electron: "N/A",
|
|
v2Wifi: "N/A",
|
|
v2Cell: "N/A",
|
|
v2WifiS3: "N/A",
|
|
v2CellS3: "N/A",
|
|
v2CellBlack: "2.1.7",
|
|
v2CellGreen: "N/A",
|
|
v2WifiBlue: "2.1.7",
|
|
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.10",
|
|
v2CellGreen: "N/A",
|
|
v2WifiBlue: "2.1.10",
|
|
v2CellBlue: "2.1.10",
|
|
v2EthBlue: "2.1.10"
|
|
}
|
|
]
|
|
]);
|
|
export class Device {
|
|
public settings: pond.DeviceSettings = pond.DeviceSettings.create();
|
|
public status: pond.DeviceStatus = pond.DeviceStatus.create();
|
|
|
|
public static create(pb?: pond.Device): Device {
|
|
let my = new Device();
|
|
if (pb) {
|
|
my.settings = pond.DeviceSettings.fromObject(or(pb.settings, {}));
|
|
my.status = pond.DeviceStatus.fromObject(or(pb.status, {}));
|
|
}
|
|
return my;
|
|
}
|
|
|
|
public static any(data: any): Device {
|
|
if (data.device) return Device.create(pond.Device.fromObject(cloneDeep(data.device)));
|
|
return Device.create(pond.Device.fromObject(cloneDeep(data)));
|
|
}
|
|
|
|
public static clone(other: Device): Device {
|
|
let my = new Device();
|
|
my.settings = pond.DeviceSettings.fromObject(cloneDeep(other.settings));
|
|
my.status = pond.DeviceStatus.fromObject(cloneDeep(other.status));
|
|
return my;
|
|
}
|
|
|
|
public id(): number {
|
|
return Number(this.settings.deviceId);
|
|
}
|
|
|
|
public name(): string {
|
|
return this.settings.name !== ""
|
|
? this.settings.name
|
|
: this.id() > 0
|
|
? "Device " + this.id()
|
|
: "";
|
|
}
|
|
|
|
public location(): pond.Location {
|
|
let loc = pond.Location.create();
|
|
loc.longitude = this.settings.longitude;
|
|
loc.latitude = this.settings.latitude;
|
|
return loc;
|
|
}
|
|
|
|
public getMarkerData(
|
|
clickFunc?: (event: React.PointerEvent<HTMLElement>, index: number, isMobile: boolean) => void,
|
|
updateFunc?: (location: pond.Location) => void
|
|
): MarkerData {
|
|
let m: MarkerData = {
|
|
longitude: this.location()?.longitude ?? 0,
|
|
latitude: this.location()?.latitude ?? 0,
|
|
title: this.name(),
|
|
colour: this.settings.theme?.color ?? "blue",
|
|
clickFunc: clickFunc,
|
|
updateFunc: updateFunc
|
|
};
|
|
return m;
|
|
}
|
|
|
|
public platformName(): string {
|
|
switch (this.settings.platform) {
|
|
case pond.DevicePlatform.DEVICE_PLATFORM_PHOTON:
|
|
return "Photon"
|
|
case pond.DevicePlatform.DEVICE_PLATFORM_ELECTRON:
|
|
return "Electron"
|
|
case pond.DevicePlatform.DEVICE_PLATFORM_V2_CELLULAR:
|
|
return "V2 Cellular"
|
|
case pond.DevicePlatform.DEVICE_PLATFORM_V2_WIFI:
|
|
return "V2 Wifi"
|
|
case pond.DevicePlatform.DEVICE_PLATFORM_V2_WIFI_S3:
|
|
return "V2 Wifi S3"
|
|
case pond.DevicePlatform.DEVICE_PLATFORM_V2_CELLULAR_S3:
|
|
return "V2 Cellular S3"
|
|
case pond.DevicePlatform.DEVICE_PLATFORM_V2_CELLULAR_BLACK:
|
|
return "V2 Cellular Black"
|
|
case pond.DevicePlatform.DEVICE_PLATFORM_V2_CELLULAR_GREEN:
|
|
return "V2 Callular Green"
|
|
case pond.DevicePlatform.DEVICE_PLATFORM_V2_WIFI_BLUE:
|
|
return "V2 Wifi Blue"
|
|
case pond.DevicePlatform.DEVICE_PLATFORM_V2_CELLULAR_BLUE:
|
|
return "V2 Cellular Blue"
|
|
case pond.DevicePlatform.DEVICE_PLATFORM_V2_ETHERNET_BLUE:
|
|
return "V2 Ethernet Blue"
|
|
default:
|
|
return "";
|
|
}
|
|
}
|
|
|
|
public maxConditions(): number {
|
|
let max = 2
|
|
switch (this.settings.platform) {
|
|
case pond.DevicePlatform.DEVICE_PLATFORM_V2_CELLULAR_BLACK:
|
|
case pond.DevicePlatform.DEVICE_PLATFORM_V2_WIFI_BLUE:
|
|
case pond.DevicePlatform.DEVICE_PLATFORM_V2_CELLULAR_BLUE:
|
|
case pond.DevicePlatform.DEVICE_PLATFORM_V2_ETHERNET_BLUE:
|
|
max = this.versionComparison(this.status.firmwareVersion, "2.1.9") ? 4 : 2;
|
|
}
|
|
return max
|
|
}
|
|
|
|
private versionComparison(deviceVersion: string, requiredVersion: string): boolean {
|
|
// Feature explicitly not supported on this platform
|
|
if (!requiredVersion || requiredVersion === "N/A") {
|
|
return false;
|
|
}
|
|
|
|
// Device firmware missing / unset
|
|
if (!deviceVersion || deviceVersion.trim() === "") {
|
|
return false;
|
|
}
|
|
|
|
//compare the versions
|
|
const parse = (v: string) => {
|
|
const [core, pre] = v.split("-");
|
|
const parts = core.split(".").map(n => parseInt(n, 10));
|
|
|
|
let preLabel = "";
|
|
let preNum = 0;
|
|
|
|
if (pre) {
|
|
const match = pre.match(/^([a-zA-Z]+)(\d*)$/);
|
|
if (match) {
|
|
preLabel = match[1].toLowerCase();
|
|
preNum = match[2] ? parseInt(match[2], 10) : 0;
|
|
}
|
|
}
|
|
|
|
return { parts, preLabel, preNum };
|
|
};
|
|
|
|
const rank = (label: string): number => {
|
|
switch (label) {
|
|
case "alpha": return 1;
|
|
case "beta": return 2;
|
|
case "rc": return 3;
|
|
default: return 0; // release
|
|
}
|
|
};
|
|
|
|
const a = parse(deviceVersion);
|
|
const b = parse(requiredVersion);
|
|
|
|
// Compare major/minor/patch
|
|
const len = Math.max(a.parts.length, b.parts.length);
|
|
for (let i = 0; i < len; i++) {
|
|
const av = a.parts[i] ?? 0;
|
|
const bv = b.parts[i] ?? 0;
|
|
if (av > bv) return true;
|
|
if (av < bv) return false;
|
|
}
|
|
|
|
// Handle prerelease vs release
|
|
if (!a.preLabel && b.preLabel) return true; // release > prerelease
|
|
if (a.preLabel && !b.preLabel) return false;
|
|
|
|
// Both prereleases → compare rank
|
|
if (a.preLabel !== b.preLabel) {
|
|
return rank(a.preLabel) >= rank(b.preLabel);
|
|
}
|
|
|
|
// Same prerelease label → compare numeric suffix
|
|
return a.preNum >= b.preNum;
|
|
}
|
|
|
|
public featureSupported(feature: string): boolean {
|
|
let versions = featureVersions.get(feature);
|
|
if (!versions) {
|
|
return false;
|
|
}
|
|
switch (this.settings.platform) {
|
|
case pond.DevicePlatform.DEVICE_PLATFORM_PHOTON:
|
|
return this.versionComparison(this.status.firmwareVersion, versions.photon);
|
|
case pond.DevicePlatform.DEVICE_PLATFORM_ELECTRON:
|
|
return this.versionComparison(this.status.firmwareVersion, versions.electron);
|
|
case pond.DevicePlatform.DEVICE_PLATFORM_V2_CELLULAR:
|
|
return this.versionComparison(this.status.firmwareVersion, versions.v2Cell);
|
|
case pond.DevicePlatform.DEVICE_PLATFORM_V2_WIFI:
|
|
return this.versionComparison(this.status.firmwareVersion, versions.v2Wifi);
|
|
case pond.DevicePlatform.DEVICE_PLATFORM_V2_WIFI_S3:
|
|
return this.versionComparison(this.status.firmwareVersion, versions.v2WifiS3);
|
|
case pond.DevicePlatform.DEVICE_PLATFORM_V2_CELLULAR_S3:
|
|
return this.versionComparison(this.status.firmwareVersion, versions.v2CellS3);
|
|
case pond.DevicePlatform.DEVICE_PLATFORM_V2_CELLULAR_BLACK:
|
|
return this.versionComparison(this.status.firmwareVersion, versions.v2CellBlack);
|
|
case pond.DevicePlatform.DEVICE_PLATFORM_V2_CELLULAR_GREEN:
|
|
return this.versionComparison(this.status.firmwareVersion, versions.v2CellGreen);
|
|
case pond.DevicePlatform.DEVICE_PLATFORM_V2_WIFI_BLUE:
|
|
return this.versionComparison(this.status.firmwareVersion, versions.v2WifiBlue);
|
|
case pond.DevicePlatform.DEVICE_PLATFORM_V2_CELLULAR_BLUE:
|
|
return this.versionComparison(this.status.firmwareVersion, versions.v2CellBlue);
|
|
case pond.DevicePlatform.DEVICE_PLATFORM_V2_ETHERNET_BLUE:
|
|
return this.versionComparison(this.status.firmwareVersion, versions.v2EthBlue);
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
}
|