Continuing the discussion from Programmatic control of BP5:
7 thoughts for anyone thinking of taking this on
Current thoughts for anyone that might take this up:
-
First, I recommend waiting until the major parsing update for commands / options is done. It’s expected that will result in a well-defined structure with explicit listing of all the options for commands, etc. … which is 95% of the work. Converting one of those commands to a protobuf message, testing, and incrementally add additional messages then becomes much easier.
-
Consider use of nanopb … which uses the ZLIB license and seems to be actively developed. There’s also a list of third-party options for various languages, in case a better option appears.
-
All fields in the
.proto
should have explicit presence. Generally, this means every field should be explicitlyoptional
orrepeated
. -
Check out the great examples
-
CAUTION: nanopb’s options include fixed-length options, but there are caveates! See Nanopb: Basic concepts for additional details.
CRITICALLY, do NOT usefixed_count
on any non-LEAF messages (messages that do not contain other messages). See secondNote
in the decoder implementation details:
Note: The decoder only keeps track of one
fixed_count
repeated field at a time. Usually this it not an issue because all elements of a repeated field occur end-to-end. Interleaved array elements of severalfixed_count
repeated fields would be a valid protobuf message, but would get rejected by nanopb decoder with error"wrong size for fixed count field"
.
-
Read about versioning best practices before working on this. Non-exhaustive examples:
-
Start small … get the infrastructure in place with some test requests / responses.
Entirely untested off-the-cuff concept
// BusPirate.proto file
syntax = "proto3"
import "nanopb.proto" // custom nanopb options directly inline
package com.buspirate.protobuf;
message BP5_test_request {
optional bool ignored = 1 [default = 0];
}
message BP5_test_response1 {
optional uint64 ticks = 1 [default = 0]; // monotonically increasing
}
message BP5_test_response2 {
optional uint32 major = 1 [deafult = 0]; // "version core"
optional uint32 minor = 2 [default = 0]; // "version core"
optional uint32 patch = 3 [default = 0]; // "version core"
repeated string prerelease = 4; // after version core, optional hyphen followed by a series of dot-separated identifiers [0-9A-Za-z-], this would hold that array of identifiers
repeated string metadata = 5; // version core and optional prerelease, optional plus sign followed by a series of dot-separated identifiers [0-9A-Za-z-], this would hold that array of identifiers
};
message BP5_request {
// Only one request at a time
oneof request {
// don't use 1-15 for test cases!
bool ignored = 19000;
BP5_test_request test1 = 19001;
BP5_test_request test2 = 19002;
}
}