@aceplus/smartace-api v2.10.0
Guide
To use the SmartAce Api in node you will need the following dependencies
"script": {
"dev": "npx tsx index.ts"
},
"dependencies": {
"@improbable-eng/grpc-web": "^0.15.0",
"@improbable-eng/grpc-web-node-http-transport": "^0.15.0",
"google-protobuf": "^3.21.2"
},
"devDependencies": {
"@types/google-protobuf": "^3.15.6",
"ts-node": "^10.9.2",
"tsx": "^4.19.2"
}
Auth
Authentication happens on the auth cluster which is located on the following URL
var AuthAddress = "https://backend-auth.smart-ace.com";
Login
To authenticate login with valid credentials
import { grpc } from "@improbable-eng/grpc-web";
import { NodeHttpTransport } from "@improbable-eng/grpc-web-node-http-transport";
import { AuthnProto } from "@aceplus/smartace-api/auth.authn_pb";
import { AuthnGRPC } from "@aceplus/smartace-api/auth.authn_pb_service";
function login(username: string, password: string): Promise<AuthnProto.AsObject> {
return new Promise(async (resolve, reject) => {
let request = new AuthnProto.LoginRequest();
request.setUsername(username);
request.setPassword(password);
grpc.invoke(AuthnGRPC.Login, {
request,
transport: NodeHttpTransport(),
host: AuthAddress,
onMessage: (res) => {
resolve(res.toObject() as AuthnProto.AsObject);
},
onEnd: (code, message) => {
if (code === 0) {
console.log("Ok");
} else {
console.log({ code, message });
reject({ code, message });
}
},
});
});
}
var auth = await login("test@email.com", "password"); // fill in your credentials here
console.log(auth.accessToken);
Refresh
Logging in gives you a accessToken that is valid for a certain amount of time. (1 hour by default)
To keep the session open, use the refresh token
import { grpc } from "@improbable-eng/grpc-web";
import { NodeHttpTransport } from "@improbable-eng/grpc-web-node-http-transport";
import { AuthnProto } from "@aceplus/smartace-api/auth.authn_pb";
import { AuthnGRPC } from "@aceplus/smartace-api/auth.authn_pb_service";
function refresh(accessToken: string, refreshToken: string): Promise<AuthnProto.AsObject> {
return new Promise(async (resolve, reject) => {
let request = new AuthnProto.RefreshRequest();
request.setAccessToken(accessToken);
request.setRefreshToken(refreshToken);
grpc.invoke(AuthnGRPC.Refresh, {
request,
transport: NodeHttpTransport(),
host: AuthAddress,
onMessage: (res) => {
resolve(res.toObject() as AuthnProto.AsObject);
},
onEnd: (code, message) => {
if (code === 0) {
console.log("Ok");
} else {
console.log({ code, message });
reject({ code, message });
}
},
});
});
}
var auth = await login("test@email.com", "password");
auth = await refresh(auth.accessToken, auth.refreshToken);
Spic
To access the spic data, we need to access the operator cluster on the following URL
var OperatorAddress = "https://backend-dev.smart-ace.com";
// grpc call helper function
function BaseOperatorRequest<TRequest extends grpc.ProtobufMessage, TResponse extends grpc.ProtobufMessage, TMethod extends grpc.MethodDefinition<TRequest, TResponse>>(
accessToken: string,
method: TMethod,
request: TRequest
): Promise<TResponse> {
return new Promise(async (resolve, reject) => {
// set accesssToken in header for authorization
const metadata = new grpc.Metadata();
metadata.set("authorization", "Bearer " + accessToken);
grpc.invoke(method, {
metadata,
request,
host: OperatorAddress,
transport: NodeHttpTransport(), // required for Node
onMessage: (res) => {
resolve(res as TResponse);
},
onEnd: (code, message) => {
if (code === 0) {
console.log("Ok");
} else {
reject({ code, message });
}
},
});
});
}
Search Cabinets
Searching cabinets with pagination
function searchCabinets(accessToken: string, name: string, count: number, page: number): Promise<CabinetProto.SearchReply> {
return new Promise(async (resolve, reject) => {
const request = new CabinetProto.SearchRequest();
name && name.length >= 3 && request.setName(name);
request.setCount(count);
request.setPage(page);
BaseOperatorRequest(accessToken, CabinetGRPC.Search, request)
.then((res) => {
resolve(res as CabinetProto.SearchReply);
})
.catch((err) => reject(err));
});
}
var cabinets = await searchCabinets(auth.accessToken, "", 10, 0);
console.log(cabinets.toObject());
let firstCabinet = cabinets.getCabinetsList()[0];
console.log(firstCabinet?.toObject());
Retrieve cabinet
Or retrieve cabinet by id or Uid
function retrieveCabinetById(accessToken: string, id: number): Promise<CabinetWithLocation> {
return new Promise(async (resolve, reject) => {
const request = new CabinetProto.RetrieveRequest();
request.setId(id);
BaseOperatorRequest(accessToken, CabinetGRPC.Retrieve, request)
.then((res) => {
resolve(res as CabinetWithLocation);
})
.catch((err) => reject(err));
});
}
function retrieveCabinetByUid(accessToken: string, uid: string): Promise<CabinetWithLocation> {
return new Promise(async (resolve, reject) => {
const request = new CabinetProto.RetrieveRequest();
request.setUid(uid);
BaseOperatorRequest(accessToken, CabinetGRPC.Retrieve, request)
.then((res) => {
resolve(res as CabinetWithLocation);
})
.catch((err) => reject(err));
});
}
let cabinet1 = await retrieveCabinetById(auth.accessToken, 1);
let cabinet2 = await retrieveCabinetByUid(auth.accessToken, "5424346F37680424");
console.log(cabinet2.toObject());
Retrieve events
function retrieveEvents(accessToken: string, cabinetId: number, count: number, page: number, descendingOrder: boolean): Promise<CabinetProto.Event.SearchReply> {
return new Promise(async (resolve, reject) => {
const request = new CabinetProto.Event.SearchRequest();
request.setCabinetId(cabinetId);
request.setCount(count);
request.setPage(page);
request.setDescorder(descendingOrder);
BaseOperatorRequest(accessToken, CabinetGRPC.SearchEvents, request)
.then((res) => {
resolve(res as CabinetProto.Event.SearchReply);
})
.catch((err) => reject(err));
});
}
let events = await retrieveEvents(auth.accessToken, cabinet2.getCabinet()!.getId(), 10, 0, false);
console.log(events.toObject());
Retrieve states
function retrieveStates(accessToken: string, uid: string, count: number, page: number, descendingOrder: boolean): Promise<CabinetProto.State.SearchReply> {
return new Promise(async (resolve, reject) => {
const request = new CabinetProto.State.SearchRequest();
request.setUid(uid);
request.setCount(count);
request.setPage(page);
request.setDescorder(descendingOrder);
request.setBatteryTo(4000);
request.setTemperatureTo(100);
BaseOperatorRequest(accessToken, CabinetGRPC.SearchStates, request)
.then((res) => {
resolve(res as CabinetProto.State.SearchReply);
})
.catch((err) => reject(err));
});
}
let states = await retrieveStates(auth.accessToken, cabinet2.getCabinet()!.getUid(), 10, 0, false);
console.log(states.toObject());
Opening a cabinet
To open a cabinet you must create a openrequest.
Here you have option for how long the opening is valid and if it is a single use or can be used multiple times withing the period
function Open(accessToken: string, cabinetId: number): Promise<CabinetProto.OpenRequest> {
return new Promise(async (resolve, reject) => {
const request = new CabinetProto.OpenRequest.CreateRequest();
request.setCabinetId(cabinetId);
function DateToTimestamp(date: Date): Timestamp {
let ts = new Timestamp();
let seconds = Math.round(date.getTime() / 1000);
ts.setSeconds(seconds);
return ts;
}
var now = new Date(Date.now());
request.setRequestTime(DateToTimestamp(now));
var expirationDate = new Date(Date.now());
expirationDate.setTime(expirationDate.getTime() + 60 * 60 * 1000);
request.setValidUntil(DateToTimestamp(expirationDate));
request.setType(CabinetProto.OpenRequest.OpenRequestType.ADMIN_OPENING);
request.setDeactivateafteropening(true);
BaseOperatorRequest(accessToken, CabinetGRPC.CreateOpenRequest, request)
.then((res) => {
resolve(res as CabinetProto.OpenRequest);
})
.catch((err) => reject(err));
});
}
let openRequest = await Open(auth.accessToken, cabinet2.getCabinet()!.getId()).catch((err) => console.log(err));
6 months ago
6 months ago
6 months ago
8 months ago
11 months ago
9 months ago
9 months ago
9 months ago
6 months ago
7 months ago
9 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
6 months ago
7 months ago
10 months ago
9 months ago
9 months ago
5 months ago
10 months ago
9 months ago
9 months ago
5 months ago
8 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
11 months ago
6 months ago
8 months ago
6 months ago
6 months ago
5 months ago
5 months ago
6 months ago
8 months ago
6 months ago
12 months ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago