BuckeyeSLI / primary_telemetry

Primary Telemetry System
GNU General Public License v3.0
0 stars 1 forks source link

Write initial version of GW5220 packet encoder/decoder #3

Open TelluriumCrystal opened 6 years ago

TelluriumCrystal commented 6 years ago

There are details on the packet structure here: Sensor Cluster RS-232 Data Protocol

The GW5220 packet decoder will be responsible for receiving packets from the RS-232 RxD lines and stripping them of start, stop, and escape flags. It will need to discard any invalid packets and generate some sort of error report. The encoder will be responsible for doing the opposite.

I would think the easiest way to do this is to write a script that monitors a single RS-232 port and then output info to a fifo pipe that the main telemetry program would read from. Because any process can put data into a pipe, you could just run another instance of the same script for every RS-232 port you want to listen to.

This could also work the other way, where each time you run the script for a port it makes a pipe for input. Then you just need to have the main telemetry program locate these pipes to know what RS-232 ports have active encoder/decoder scripts running, and then send the necessary messages down those pipes.

Axodah commented 6 years ago

I'm pretty sure that would result in a producer consumer problem, and would require its own pipe permission access script to handle and prevent simultaneous access. Unless i/o to the pipe is atomic (which is probably not directly possible, as an rs232 read and a pipe write together aren't atomic), things could get bloated. I'm sure there is a convention to do it. I'll do some research this weekend after we get everything together. Some delicacy is required when doing 1 consumer to multiple producer access control without bogging it down.

Axodah commented 6 years ago

The second solution may be more feasible, as inter-process pipes that are full duplex are designed for just that sort of communication. We can use the main process to open individual processes with pipes to call back to the main process using message passing, so everything is contained with as little bloat as possible. These pipes can be opened when we find a startup message in an rs232 buffer, so can dynamically be assigned. Following that section (probably timed), it can simply wait for messages. Once received, encode and send whatever is necessary.

TelluriumCrystal commented 6 years ago

Yes, I just read up more on how fifos work and there would definitely be issues with having a single fifo pipe written to by several processes. Strange things could happen with writes happening at the same time, but more importantly there is no inherent data separation. We would need to add start and stop bytes, which kind of defeats the point of having a decoder in the first place. It would seem the correct solution here is to use Unix Domain Sockets, which is essentially UDP between processes with guaranteed delivery.

Using this system I don't think we will have a producer consumer problem, mainly because it should be impossible for the RS-232 input to outpace the rate the main program is processing messages. I would expect the main program to spend upwards of 70% of its runtime just waiting for a new message to arrive. We don't need to have dynamic detection, we will know which RS-232 inputs we care about and tell the main program at the start or define it in a config file.

So the way this would work then is the main program will start and either take input or read a config file to determine which RS-232 ports it will be using. First it will create another process to handle incoming packets from wifi. It will then run a separate process for each port and set up a stream using Unix Domain Sockets. Then it would listen to its own socket for input from the RS-232 ports. Meanwhile the wifi packet process would just wait for an incoming packet, then either execute the contents of the packet or forward it to the respective RS-232 port's socket.

How does that sound?

TelluriumCrystal commented 6 years ago

You'd probably need to make the encoders and decoders separate processes so they can just listen to the stream they care about without needing to worry about polling multiple streams. So basically this:

Where "blocking socket read" is supposed to say "blocking socket read/write".

It probably doesn't matter if the main process is the one that reads or writes to the TCP/UDP socket. It might actually make more sense to have a separate main program that administrates all the child processes.