Welcome toVigges Developer Community-Open, Learning,Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
2.2k views
in Technique[技术] by (71.8m points)

angular - Protocol Buffers in Ionic

Attempting to use Protocol Buffers in Ionic 4 to encode & decode messages. Have tried to use protobufjs and also google-protobuf, but can't get either to work.

I have downloaded the protoc and used it to generate a bunch of _pb.js files, one for each .proto file. That's fine.

Focusing on the protobuf example first. Here's the example code:

import { load } from "protobufjs"; // respectively "./node_modules/protobufjs"

load("awesome.proto", function(err, root) {
  if (err)
    throw err;

  // example code
  const AwesomeMessage = root.lookupType("awesomepackage.AwesomeMessage");

  let message = AwesomeMessage.create({ awesomeField: "hello" });
  console.log(`message = ${JSON.stringify(message)}`);

  let buffer = AwesomeMessage.encode(message).finish();
  console.log(`buffer = ${Array.prototype.toString.call(buffer)}`);

  let decoded = AwesomeMessage.decode(buffer);
  console.log(`decoded = ${JSON.stringify(decoded)}`);
});

I make a few changes to match my files. change the name of the proto file. But my proto file doesn't have a package name in it. So I just used the message name. Firstly here's the start of my .proto file:

syntax = "proto3";

import "constants.proto";
import "wifi_constants.proto";

message CmdScanStart {
    bool blocking = 1;
    bool passive = 2;
    uint32 group_channels = 3;
    uint32 period_ms = 4;
}

message RespScanStart {

}

message CmdScanStatus {

}

message RespScanStatus {
    bool scan_finished = 1;
    uint32 result_count = 2;
}

Now here's the code as I've changed it:

load("../../assets/proto/wifi_scan.proto", function(err, root) {
      if (err)
      throw err;

      // example code
      const AwesomeMessage = root.lookupType("RespScanStatus");

      let message = AwesomeMessage.create({ scan_finished: 1, result_count: 31 }); // uint32 result_count
      console.log(`message = ${JSON.stringify(message)}`);

      let buffer = AwesomeMessage.encode(message).finish();
      console.log(`buffer = ${Array.prototype.toString.call(buffer)}`);

      let decoded = AwesomeMessage.decode(buffer);
      console.log(`decoded = ${JSON.stringify(decoded)}`);

    });

It doesn't seem to work. My console shows this:

[ng] [console.log]: "message = {}"
[ng] [console.log]: "buffer = "
[ng] [console.log]: "decoded = {}"

I believe I've ssussessfuly poited to the file and chosen a valid message name. But If I have a proto file that references other proto files. How is this resolved at runtime? I assumed using prebuilt _pb.js files would make more sense. What is awesomepackage? My proto file has no packages! Why the incessant reference to awesome things? Not awesome: confusing!

This code looks like it can directly consume the .proto file. But won't you need protoc to do this? Which won't necessarily be available. This may seem obvious if you know what's going on, but it's not quite coming together for me. help please.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

One possible answer is to use google-protobuf. See https://github.com/protocolbuffers/protobuf/tree/master/js

$ npm install google-protobug --save

Now as per the question, use protoc to generate a set of _pb.js files. Select the common JS import style when you run your commands so the next step lines up with your outputs:

$ protoc --proto_path=./proto-src-wifi/ --js_out=import_style=commonjs,binary:./proto-js ./proto-src-wifi/wifi_scan.proto

This creates a _pb.js files which you can now use in your angular project. I found that something like this worked well to generate heaps at a time:

$ protoc --proto_path=./proto-src-wifi/ --js_out=import_style=commonjs,binary:./proto-js ./proto-src-wifi/*.proto

You can import them using like this for wifi_scan_pb:

    console.log('armpit!'); 
    var messages = require("../../assets/js/wifi_scan_pb");
    var message = new messages.RespScanStatus();
    message.setScanFinished(true);
    message.setResultCount(31);
    var bytesOfStuff = message.serializeBinary();
    console.log(`bytesOfStuff = ${JSON.stringify(bytesOfStuff)}`); 

    var messageRecovered = messages.RespScanStatus.deserializeBinary(bytesOfStuff);
    console.log(`Recovered Scan finished = ${messageRecovered.array[0]}`);
    console.log(`Recovered Scan Result Count = ${messageRecovered.array[1]}`);

You'll need to check the _pb file to get the exact name of the method you need to use for each entry in the object you're building: 'setScanFinished' or whatever...

And above the component:

declare var require: any;

Does the job!


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to Vigges Developer Community for programmer and developer-Open, Learning and Share
...