can provision devices

This commit is contained in:
Carter 2024-12-09 17:26:12 -06:00
parent 0ae37f1370
commit 03f8ed20ca
18 changed files with 1467 additions and 17 deletions

View file

@ -0,0 +1,668 @@
import { useHTTP, usePermissionAPI } from "hooks";
// import { useWebsocket } from "websocket";
import { /*Component,*/ deviceScope, User } from "models";
import { pond } from "protobuf-ts/pond";
import { createContext, PropsWithChildren, useContext } from "react";
import { pondURL } from "./pond";
import { AxiosResponse } from "axios";
import { useGlobalState } from "providers";
import { dateRange } from "providers/http";
import moment from "moment";
export interface IDeviceAPIContext {
add: (name: string, description: string, backpack: pond.BackpackSettings) => Promise<any>;
update: (id: number, settings: pond.DeviceSettings) => Promise<any>;
remove: (id: number) => Promise<any>;
get: (id: number | string, demo?: boolean, keys?: string[], types?: string[]) => Promise<any>;
getPageData: (
id: number | string,
keys?: string[],
types?: string[]
) => Promise<AxiosResponse<pond.GetDevicePageDataResponse>>;
getMulti: (ids: number[] | string[]) => Promise<any>;
getGeoJson: (id: number | string, demo?: boolean) => Promise<any>;
getMultiGeoJson: (ids: number[] | string[]) => Promise<any>;
list: (
limit: number,
offset: number,
order?: "asc" | "desc",
orderBy?: string,
search?: string,
settings?: string,
status?: string,
ids?: number[] | string[] | Long[],
asRoot?: boolean,
comprehensive?: boolean,
withMeasurements?: boolean,
keys?: string[],
types?: string[]
) => Promise<AxiosResponse<pond.ListDevicesResponse>>;
listForUser: (
asRoot: boolean,
user?: string,
search?: string,
hologram?: boolean,
keys?: string[],
types?: string[]
) => Promise<AxiosResponse<pond.ListDevicesResponse>>;
claim: (id: number | Long, body: any) => Promise<any>;
listHistory: (id: number, limit: number, offset: number) => Promise<any>;
listCompleteHistory: (
id: number,
limit: number,
offset: number,
filters?: pond.ObjectType[]
) => Promise<AxiosResponse<pond.ListCompleteHistoryResponse>>;
updatePermissions: (id: number | string, users: User[]) => Promise<any>;
updatePreferences: (
id: number | string,
preferences: pond.UserPreferences,
keys?: string[],
types?: string[]
) => Promise<any>;
updateComponentPreferences: (
id: number | string,
component: string,
preferences: pond.DeviceComponentPreferences,
keys?: string[],
types?: string[]
) => Promise<any>;
listDeviceComponentPreferences: (
id: number | string,
keys?: string[],
types?: string[]
) => Promise<AxiosResponse<pond.ListDeviceComponentPreferencesResponse>>;
updateStatus: (
id: number | string,
status: pond.DeviceStatus,
keys?: string[],
types?: string[]
) => Promise<any>;
sync: (id: number) => Promise<any>;
clearPending: (id: number) => Promise<any>;
pause: (id: number) => Promise<any>;
bulkPause: (
ids: number[],
setPaused: boolean
) => Promise<AxiosResponse<pond.BulkPauseDeviceResponse>>;
bulkChangeDataCaps: (
ids: number[],
newCap: number
) => Promise<AxiosResponse<pond.BulkChangeDataCapsResponse>>;
resume: (id: number) => Promise<any>;
getUpgradeStatus: (id: number, keys?: string[], types?: string[]) => Promise<any>;
loadBackpack: (id: number, backpack: number) => Promise<any>;
setTags: (id: number, tags: string[]) => Promise<any>;
setWifi: (
id: number,
gateway: string,
password: string,
keys?: string[],
types?: string[]
) => Promise<any>;
tag: (id: number, tag: string) => Promise<any>;
untag: (id: number, tag: string) => Promise<any>;
getDatacap: (id: number) => Promise<any>;
isOverLimit: (id: number) => Promise<any>;
isPaused: (id: number) => Promise<any>;
setDatacap: (id: number, newCap: number) => Promise<any>;
// listJSONMeasurements: (
// id: number,
// components: Component[],
// startDate: any,
// endDate: any,
// limit: number,
// offset: number,
// order: string,
// orderBy: string
// ) => Promise<AxiosResponse<pond.ListDeviceExportedMeasurementsResponse>>;
listSimpleJSON: (device: number) => Promise<any>;
resetQuackCount: (id: number) => Promise<any>;
resetQuackCountTx: (id: number) => Promise<any>;
resetQuackCountTx1000: (id: number) => Promise<any>;
linearMutation: (
id: number,
mutation: pond.LinearMutation
) => Promise<AxiosResponse<pond.DeviceLinearMutationResponse>>;
getDataUsage: (id: number, start?: any) => Promise<any>;
buyData: (
id: number | string,
MB: number,
source?: string,
keys?: string[],
types?: string[]
) => Promise<any>;
}
export const DeviceAPIContext = createContext<IDeviceAPIContext>({} as IDeviceAPIContext);
interface Props {}
export default function DeviceProvider(props: PropsWithChildren<Props>) {
const { children } = props;
const { get, post, put, del } = useHTTP();
const permissionAPI = usePermissionAPI();
const [{ as, team }] = useGlobalState();
const add = (name: string, description: string, backpack: pond.BackpackSettings) => {
if (as) return post(pondURL("/devices?as=" + as), { name, description, backpack });
return post(pondURL("/devices"), { name, description, backpack });
};
const getDevice = (
id: number | string,
demo: boolean = false,
keys?: string[],
types?: string[]
) => {
if (as && !(types && types.length > 0 && types[0] === "team"))
return get(
pondURL(
"/devices/" +
id +
"?as=" +
as +
(keys ? "&keys=" + keys.toString() : "") +
(types ? "&types=" + types.toString() : ""),
demo
)
);
const url = pondURL(
"/devices/" +
id +
(keys ? "?keys=" + keys.toString() : "") +
(types ? "&types=" + types.toString() : ""),
demo
);
return get(url);
};
const getDevicePageData = (
id: number | string,
keys?: string[],
types?: string[]
): Promise<AxiosResponse<pond.GetDevicePageDataResponse>> => {
if (as && !(types && types.length > 0 && types[0] === "team"))
return get(
pondURL(
"/devicePageData/" +
id +
"?as=" +
as +
(keys ? "&keys=" + keys.toString() : "") +
(types ? "&types=" + types.toString() : "")
)
);
const url = pondURL(
"/devicePageData/" +
id +
(keys ? "?keys=" + keys.toString() : "") +
(types ? "&types=" + types.toString() : "")
);
return get<pond.GetDevicePageDataResponse>(url);
};
const getDeviceGeoJSON = (id: number | string, demo: boolean = false) => {
if (as) return get(pondURL("/devices/" + id + "/geojson?as=" + as, demo));
const url = pondURL("/devices/" + id + "/geojson", demo);
return get(url);
};
const getMulti = (ids: number[] | string[]) => {
let idString = "";
ids.forEach((id: number | string, i: number) => {
if (i === 0) {
idString = idString + id;
} else {
idString = idString + "," + id;
}
});
if (as) return get(pondURL("/multidevices?devices=" + idString + "&as=" + as));
return get(pondURL("/multidevices?devices=" + idString));
};
const getMultiDevicesGeoJSON = (ids: number[] | string[]) => {
let idString = "";
ids.forEach((id: number | string, i: number) => {
if (i === 0) {
idString = idString + id;
} else {
idString = idString + "," + id;
}
});
if (as) return get(pondURL("/geojson/devices?devices=" + idString + "&as=" + as));
return get(pondURL("/geojson/devices?devices=" + idString));
};
const list = (
limit: number,
offset: number,
order?: "asc" | "desc",
orderBy?: string,
search?: string,
settings?: string,
status?: string,
ids?: number[] | string[] | Long[],
asRoot?: boolean,
comprehensive?: boolean,
withMeasurements?: boolean,
keys?: string[],
types?: string[]
) => {
const url = pondURL(
"/devices" +
"?limit=" +
limit +
"&offset=" +
offset +
("&order=" + (order ? order : "asc")) +
("&by=" + (orderBy ? orderBy : "deviceId")) +
(search ? "&search=" + search : "") +
(settings ? "&settings=" + settings : "") +
(status ? "&status=" + status : "") +
(ids ? "&ids=" + ids.join(",") : "") +
(asRoot ? "&asRoot=" + asRoot.toString() : "") +
(as && !(types && types.length > 0 && types[0] === "team") ? "&as=" + as : "") +
(comprehensive ? "&comprehensive=" + comprehensive.toString() : "") +
(withMeasurements ? "&measurements=" + withMeasurements.toString() : "") +
(keys ? "&keys=" + keys.toString() : "") +
(types ? "&types=" + types.toString() : "")
);
return get<pond.ListDevicesResponse>(url);
};
const listForUser = (
asRoot: boolean,
user?: string,
search?: string,
hologram?: boolean,
keys?: string[],
types?: string[]
) => {
const url = pondURL(
"/devices" +
(user ? "?as=" + user : "?asRoot=" + asRoot.toString()) +
(search ? "&search=" + search : "") +
(hologram ? "&hologram=" + hologram.toString() : "") +
(keys ? "&keys=" + keys.toString() : "") +
(types ? "&types=" + types.toString() : "")
);
return get<pond.ListDevicesResponse>(url);
};
const remove = (id: number) => {
if (as) return del(pondURL("/devices/" + id + "?as=" + as));
const url = pondURL("/devices/" + id);
return del(url);
};
const update = (id: number, settings: pond.DeviceSettings) => {
if (as) return put(pondURL(`/devices/${id}/update?as=${as}`), settings);
const url = pondURL("/devices/" + id + "/update");
return put(url, settings);
};
const claim = (id: number | Long, body: any) => {
return put(pondURL("/devices/" + id), body);
};
const listHistory = (id: number, limit: number, offset: number) => {
return get(pondURL("/devices/" + id + "/history?limit=" + limit + "&offset=" + offset));
};
const listCompleteHistory = (
id: number,
limit: number,
offset: number,
filters?: pond.ObjectType[]
) => {
return get<pond.ListCompleteHistoryResponse>(
pondURL(
"/devices/" +
id +
"/completehistory?limit=" +
limit +
"&offset=" +
offset +
(filters ? "&sources=" + filters.toString() : "")
)
);
};
const updateDevicePermissions = (id: number | string, users: User[]) => {
return permissionAPI.updatePermissions(deviceScope(id.toString()), users);
};
const updatePreferences = (
id: number | string,
preferences: pond.UserPreferences,
keys?: string[],
types?: string[]
) => {
return put(
pondURL(
"/devices/" +
id +
"/preferences" +
"?as=" +
as +
(keys ? "&keys=" + keys.toString() : "") +
(types ? "&types=" + types.toString() : "")
),
preferences
);
};
const updateComponentPreferences = (
id: number | string,
component: string,
preferences: pond.DeviceComponentPreferences,
keys?: string[],
types?: string[]
) => {
return put(
pondURL(
"/devices/" +
id +
"/components/" +
component +
"/componentPreferences" +
"?as=" +
as +
(keys ? "&keys=" + keys.toString() : "") +
(types ? "&types=" + types.toString() : "")
),
preferences
);
};
const listDeviceComponentPreferences = (
id: number | string,
keys?: string[],
types?: string[]
) => {
return get<pond.ListDeviceComponentPreferencesResponse>(
pondURL(
"/devices/" +
id +
"/componentPreferences?as=" +
as +
(keys ? "&keys=" + keys.toString() : "") +
(types ? "&types=" + types.toString() : "")
)
);
};
const updateStatus = (
id: number | string,
status: pond.DeviceStatus,
keys?: string[],
types?: string[]
) => {
return put(
pondURL(
"/devices/" +
id +
"/updateStatus" +
"?as=" +
as +
(keys ? "&keys=" + keys.toString() : "") +
(types ? "&types=" + types.toString() : "")
),
status
);
};
const sync = (id: number) => {
return post(pondURL("/devices/" + id + "/sync"), {});
};
const clearPending = (id: number) => {
return post(pondURL("/devices/" + id + "/clearPending"), {});
};
const pause = (id: number) => {
return post(pondURL("/devices/" + id + "/pause"), {});
};
const bulkPause = (ids: number[], setPaused: boolean) => {
return post<pond.BulkPauseDeviceResponse>(
pondURL(
"/bulkPauseDevices?ids=" +
ids.toString() +
(setPaused ? "&pause=" + setPaused.toString() : "")
),
{}
);
};
const bulkChangeDataCaps = (ids: number[], newCap: number) => {
return post<pond.BulkChangeDataCapsResponse>(
pondURL("/bulkChangeDataCap?ids=" + ids.toString() + "&dataCap=" + newCap),
{}
);
};
const resume = (id: number) => {
return post(pondURL("/devices/" + id + "/resume"), {});
};
const getUpgradeStatus = (id: number, keys?: string[], types?: string[]) => {
let a = as ? "?as=" + as : "";
if (keys && keys.length > 0 && types && types.length > 0) {
a = as ? a + "&keys=" + keys + "&types=" + types : "?keys=" + keys + "&types=" + types;
}
let url = pondURL("/devices/" + id + "/firmware" + a);
return get(url);
};
const loadBackpack = (id: number, backpack: number) => {
return put(pondURL("/devices/" + id + "/load/" + backpack), {});
};
const setTags = (id: number, tags: string[]) => {
return put(pondURL("/devices/" + id + "/tags"), { tags });
};
const setWifi = (
id: number,
gateway: string,
password: string,
keys?: string[],
types?: string[]
) => {
let a = as ? "?as=" + as : "";
if (keys && keys.length > 0 && types && types.length > 0) {
a = as ? a + "&keys=" + keys + "&types=" + types : "?keys=" + keys + "&types=" + types;
}
return put(pondURL("/devices/" + id + "/wifi" + a), { gateway, password });
};
const tag = (id: number, tag: string) => {
return put(pondURL("/devices/" + id + "/tags/" + tag), {});
};
const untag = (id: number, tag: string) => {
return del(pondURL("/devices/" + id + "/tags/" + tag));
};
const getDatacap = (id: number) => {
return get(pondURL("/devices/" + id + "/datacap/"));
};
const isOverLimit = (id: number) => {
return get(pondURL("/devices/" + id + "/overlimit/"));
};
const isPaused = (id: number) => {
return get(pondURL("/devices/" + id + "/paused/"));
};
const setDatacap = (id: number, newCap: number) => {
return post(pondURL("/devices/" + id + "/datacap?limit=" + newCap));
};
const getDataUsage = (id: number, start?: any) => {
if (start) {
start = "?start=" + moment(start).toISOString();
} else {
start = "";
}
return get(pondURL("/devices/" + id + "/usage/" + start));
};
// const listJSONMeasurements = (
// id: number,
// components: Component[],
// startDate: any,
// endDate: any,
// limit: number,
// offset: number,
// order: string,
// orderBy: string
// ) => {
// let keyString = "";
// components.forEach((comp, i) => {
// if (i === 0) {
// keyString = keyString + comp.key();
// } else {
// keyString = keyString + "," + comp.key();
// }
// });
// if (as) {
// return get<pond.ListDeviceExportedMeasurementsResponse>(
// pondURL(
// "/devices/" +
// id +
// "/measurements/exportComplex" +
// dateRange(startDate, endDate) +
// "&components=" +
// keyString +
// "&limit=" +
// limit +
// "&offset=" +
// offset +
// "&order=" +
// order +
// "&orderBy=" +
// orderBy +
// "&as=" +
// as
// )
// );
// }
// return get<pond.ListDeviceExportedMeasurementsResponse>(
// pondURL(
// "/devices/" +
// id +
// "/measurements/exportComplex" +
// dateRange(startDate, endDate) +
// "&components=" +
// keyString +
// "&limit=" +
// limit +
// "&offset=" +
// offset +
// "&order=" +
// order +
// "&orderBy=" +
// orderBy
// )
// );
// };
const listSimpleJSON = (device: number) => {
return get(pondURL("/devices/" + device + "/measurements/exportSimple"));
};
const resetQuackCount = (id: number) => {
return post(pondURL("/devices/" + id + "/resetCounts"));
};
const resetQuackCountTx = (id: number) => {
return post(pondURL("/devices/" + id + "/resetCountTx"));
};
const resetQuackCountTx1000 = (id: number) => {
return post(pondURL("/devices/" + id + "/partialResetCountTx"));
};
const linearMutation = (id: number, mutation: pond.LinearMutation) => {
return post<pond.DeviceLinearMutationResponse>(
pondURL("/devices/" + id + "/linearMutation"),
mutation
);
};
const buyData = (
id: number | string,
MB: number,
source?: string,
keys?: string[],
types?: string[]
) => {
let url = "/devices/" + id + "/buyData?MB=" + MB;
if (as === team.key()) url = url + "&team=" + team.key();
if (source) url = url + "&source=" + source;
if (keys) url = url + "&keys=" + keys;
if (types) url = url + "&types=" + types;
return put(pondURL(url));
};
return (
<DeviceAPIContext.Provider
value={{
add,
update,
remove,
get: getDevice,
getPageData: getDevicePageData,
getMulti,
getGeoJson: getDeviceGeoJSON,
getMultiGeoJson: getMultiDevicesGeoJSON,
list,
claim,
listHistory,
listCompleteHistory,
updatePermissions: updateDevicePermissions,
updateStatus,
updatePreferences,
clearPending,
sync,
pause,
bulkPause,
bulkChangeDataCaps,
resume,
getUpgradeStatus,
loadBackpack,
setTags,
setWifi,
tag,
untag,
getDatacap,
isOverLimit,
isPaused,
setDatacap,
// listJSONMeasurements,
listSimpleJSON,
resetQuackCount,
resetQuackCountTx,
resetQuackCountTx1000,
listForUser,
linearMutation,
getDataUsage,
buyData,
updateComponentPreferences,
listDeviceComponentPreferences
}}>
{children}
</DeviceAPIContext.Provider>
);
}
export const useDeviceAPI = () => useContext(DeviceAPIContext);
// export const useDeviceWebsocket = (
// id: number | string,
// emitter: (m: any) => void,
// rate: number = 0
// ) => useWebsocket("/devices/" + id, m => Device.any(JSON.parse(m.data)), emitter, rate);