-
Notifications
You must be signed in to change notification settings - Fork 31
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
separate protocol and implementation? #1
Comments
Yes, I don't think it makes sense to force users of Device to have a serial port. Would it make sense to template Device on the port type (which is now a We could have a RS232-friendly wrapper, and a SPI-friendly wrapper, as features though. We'd probably have to change how the poll_for method works, but I think that's fine. |
Not sure that it is possible to create effective abstraction. Plus it is possible to have several devices connected via SPI to CPU. And you activate gpio1 or gpio2 to choose your preferable device. The problem in this configuration is that "Device" object that control spi is may be not corresponding to only GPS, |
Perfect image of crate for me, is UBX protocol state machine parser - you give it bytes and it time to time give to you packets, plus packet unpacker, plus functions to create packets. Parser is preferably based on nom but this is just preference. |
Yeah, SPI's simultaneous read/write model does not match well with the RS232 model. I very much like |
I can make some prototypes for what such a class might look like this weekend. |
Plus I should add that serial crate that use as dependency (serialport) may be not suitable for all use cases. For example I use "Raspberry Pi 3" for work with navigation device, there is nice crate for it: rppal. It covers almost all interfaces that I need: i2c, spi and uart. So if my gps receiver will be connected via serial port (it doesn't, but if) then I will be prefer to use rppal crate for work with uart, because of I already uses it for other interfaces. |
Good point. I just pushed a commit which splits up the parsing from all the I/O dependencies and policy - now you can use the Usage looks something like:
Thoughts? |
I like general idea, here some remarks:
And it would be great to remove all dependencies, my dependencies tree is now huge enough, |
The packets are all simple enough I can get away with
Some packets, like the response for Though I suppose, the packets could implement the EDIT: Or for writing, the |
Oh, this is unexpected for me, because of there is no guarantee about preserving of binary format between major versions update, so it need something like 100% test coverage for easy way to migrate between major releases, but this is interesting way for parse such simple structures.
Or may be it can be lazy parsing, extracting only what need user and without even use additional memory, like:
So structures would hold already packed data and use getters to get exactly what user want and only that fields. It save some CPU cycles, plus parser can return The downside of this idea is that there is need for some kind of builder pattern for simplify way to construct them, plus it should be some kind of macros or "derive" crate that simplify description of getters and constructors based on "build pattern", but it can reduce dependency graph to something like syn/quote. |
I don't think constructing structures like that will be too hard, since they could be constructed much the way they are now, and there would be an easy way to handle different protocol versions (since the class I don't know whether the parser would be able to return a
Zero copies required, with a usage like:
The trick being that any given packet has to be a continuous chunk in memory. You're right though, that some sort of macro or derive crate would have to be created to build all the views. I don't know much about building macros in Rust (just a little bit about macro_rules), but I've been looking for a good opportunity to learn :) |
For sending I don't see why use references, that's why I describe two types: Foo and FooRef, Like:
If you some strange reason want to send Nav-PosLLH you need Though may be better Segmenter::consume_one. Because of So I don't see any issues with "continuous chunk in memory".
I don't think that with syn/quote you have to learn something worth to mention. In general you just:
and you already has analog of |
I've spent a bit of time poking around with syn/quote, I agree it won't be too hard to make a handy little macro to generate getters. Maybe I can even get it to handle bitfields:
Or something.
Inconveniently,
The Instead of a
It's a bit unwieldy of an API, since you're doing all your own buffer management, but that might be fine if you're in a particularly restricted environment. To your point though, it would be convenient for sending packets, since you could build them in-place in a transmit buffer, if the structs all had setters. |
Actually it can be circular buffer, but not for bytes, but for packets. |
I made prototype to benchmark different parser implementations. Three implementations:
I measure time with clock(3) functions from libc and run benchmark several times:
So I suppose I start work with parser that uses (3) as main strategy, |
This need for future steps, like separate protocol parser/generator, and code generators ref ublox-rs#1
Cool! I did end up playing around a bit with syn/quote, and wrote up some of the packets to that. It includes generating views into packets, so I think it wouldn't be too hard to write Packet::deserialize so that it returns a packet view. I haven't had a chance to port all of the packets to this system, but I pushed what I have done. |
Great, I need to start communicate with my ublox receiver ASAP. |
The derive macro should be able to represent any packet, except I think ones with strings (or any generic array of bytes). If you need to parse one of those I might be able to whip something up later (I'm out most of today though), but also just handwriting something wouldn't be too bad. |
There are many things that were out of our discussion, but nice to have. Also it would be nice to have mapper functions, like: #[derive(UbxProtocolRecv)]
struct NavPosLlh {
#[ubx_protocol(map= "lat_degree")]
lat: i32,
}
fn lat_degree(lat: i32) -> f64 {
f64::from(lat) * 1e-7
} and as result it generate getter for This is because of scaling via 1e-7 is part of protocol, so I don't see why user of crate should care about this. I suppose I will add missed thing during work with this crate and make PR. |
As it is now, it generates both a Ref view and a MutRef view, so as long as you have a buffer to write into, you can set fields as desired. It generates getter and setter traits as well. I like the mapper idea, although |
Features: - removes unnecessary dependicies - more type safe code - faster parser: 3x fixes ublox-rs#1
Features: - removes unnecessary dependicies - more type safe code - faster parser: 3x fixes ublox-rs#1
Features: - removes unnecessary dependicies - more type safe code - faster parser: 3x fixes ublox-rs#1
* Use own proc macro to generate code to deal with packets Features: - removes unnecessary dependicies - more type safe code - faster parser: 3x fixes #1 * make all names in ubx_packets starts with Ubx for uniformity * export packet size as constant Usefull for SPI, where we need provide read buffer simultaneously with write buffer * feature: make possible to print (+validate) extension field in MonVer * feature: new packages: Nav-Dop, Nav-Sol, AckNak * feature: nice method to check if ack for certain message * fix: generted code for handling i8 field in ubx_packet_recv * cleanups/typo fixes plus formating * fix several clippy warnings * parser/refactoring: simplify work with &data[pos..] * parser_tests/refactroing: split big test into small one * make possible to reuse ublox dump test * feature: automatically calculate max packet size for parser * refactoring: rename CfgMsg(3|8) -> CfgMsg(Single|All)Port(s) * feature: Debug implementation for FixStatusInfo * ublox_derive/src/input refactoring: use "use syn::Error" * ublox_derive: check that rest_handling not already defined * refactoring: simplify generate_send_code_for_packet * fix comment grammar * ublox_derive/src/input: improve error message * fix tests * refactoring: usage of fold, plus more appropriate names
@lkolbly
I use ublox GPS receiver, but it is connected via SPI on my board.
Do you interesting split this crate into two: one for UBX protocol and other part with rs232 and so on?
The text was updated successfully, but these errors were encountered: