2.10.0 • Published 5 months ago

@aceplus/smartace-api v2.10.0

Weekly downloads
-
License
-
Repository
-
Last release
5 months ago

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));
2.9.0-alpha.10

6 months ago

2.9.0-alpha.11

6 months ago

2.9.0-alpha.12

6 months ago

2.7.0-alpha.1

8 months ago

2.2.0

11 months ago

2.4.1

9 months ago

2.4.0

9 months ago

2.6.0

9 months ago

2.8.1

6 months ago

2.8.0

7 months ago

2.4.0-alpha.4

9 months ago

2.9.0-alpha.1

7 months ago

2.9.0-alpha.4

7 months ago

2.9.0-alpha.2

7 months ago

2.9.0-alpha.3

7 months ago

2.9.0-alpha.8

7 months ago

2.9.0-alpha.9

6 months ago

2.9.0-alpha.7

7 months ago

2.3.0

10 months ago

2.5.0

9 months ago

2.3.2

9 months ago

2.10.0

5 months ago

2.3.1

10 months ago

2.5.1

9 months ago

2.3.3

9 months ago

2.9.0

5 months ago

2.7.1

8 months ago

2.9.0-alpha.24

5 months ago

2.9.0-alpha.25

5 months ago

2.9.0-alpha.26

5 months ago

2.9.0-alpha.27

5 months ago

2.9.0-alpha.28

5 months ago

2.2.0-alpha.1

11 months ago

2.9.0-alpha.20

6 months ago

2.8.0-alpha.1

8 months ago

2.9.0-alpha.22

6 months ago

2.9.0-alpha.23

6 months ago

2.10.0-alpha.2

5 months ago

2.10.0-alpha.1

5 months ago

2.9.0-alpha.13

6 months ago

2.1.0

12 months ago

2.0.0

1 year ago

1.3.0-alpha.131

1 year ago

1.3.0-alpha.130

1 year ago

1.3.0-alpha.129

1 year ago

1.3.0-alpha.127

1 year ago

1.3.0-alpha.126

1 year ago

1.3.0-alpha.125

1 year ago

1.3.0-alpha.124

1 year ago