Emulator Library

Topics: Emulator Library
Coordinator
Dec 4, 2010 at 3:39 AM

This library should decouple the business logic from the front end UI so the UI’s code will be cleaner to read. I have given you all of the methods that I think you will need in ERIO.cs and added extensive documentation so you should be able to figure out what they do. I’ve also opened a ticket for you, so you can close that when you are done. Let me know if you have any questions or concerns about the API or implementation.

Coordinator
Dec 4, 2010 at 3:40 AM

scrabble:

I do have a few questions:

  1. What is the point of allowing the UDPClient to listen synchronously? That prevents the entire program from doing anything else until the packet arrives, no?
  2. ParseHumanReadable(). Would it make more sense to break the server packet down into a FountainState object or something similar? I feel like, some way or another, it should be stored as an object anyway (testing a Boolean seems easier than searching through and parsing the intermediate form of List<String> that this method produces).
  3. Actually, is it possible/sensible for the library to be "always listening" and just raise an event or something similar whenever a packet arrives?
  4. Should the Library automatically parse packets and update the state of the emulator?

Oh jeez, I started questioning almost everything here... hmmm... I guess perhaps you can resolve all of those questions by giving a motivation behind your design structure. It seems like I was almost walking towards (given the questions I was asking) a separate executable to sit as the "business logic" layer. I think it would do a better job isolating the UI from the underlying communication, since so many things are happening asynchronously, but I also think it would be a programming hell to get two different processes to communicate.

Let me know what you think. I feel like I didn't make a whole lot of sense there; let me know if that's the case.

Coordinator
Dec 4, 2010 at 3:41 AM

Excellent questions!


1. There is no real justification for doing this synchronously (at least when I first wrote this, see point 4)! You got me. I added it thinking that it might be easier to code up and in some situations where there is no input (e.g. console application) there would be nothing else to do while blocking waiting for packet. This is probably a silly assumption, and you can toss that method out (although, wait until reading #4 before removing it). (So I guess you should keep it. I don't know).
2. It would also make sense to create a FountainState object (as OOP is all about objects relating to real world things). You could define an object to do this, but I would (and did) create a List<bool> for all of the attributes (e.g. List<bool> pumps).
3. Everything is possible in software! In many cases, there is no one right design answer. First option: the library will only listen when the program wants it to. When the program receives that packet, it can do whatever it want to and then makes a call back to the library for the next packet. The downside is that you may have missed a few packets. Second option: you can receive a packet whenever. You will be sure to receive all of the packets, but then you may have issues if you try to process multiple packets at the same time (depends on how you implement your UI). Just run it though your head a few times and whichever one makes the most sense to you, implement it.
4. No and yes. There may be instances that you will want to have the raw packet from the client (e.g. so you print it out and make sure it looks okay). If you wanted, you could make a separate method that will return the new state. This is complicated though because of the asynchronous nature of networking. If you do a synchronous call, the result is retained within the library and can be parsed. I have modified the ListenSync method such that it will return the byte[] received and the human readable object. If you do an asynchronous call, the result will be in the hands of whatever called the method and will have to be resent into the library for processing.

This is good that you are asking these types of questions. The last thing you mentioned in the paragraph I don't quite understand. A library are a set of method calls that are hidden from the UI that allow the UI to focus mainly on doing UI stuff without caring about what is actually going on. Also, a library is not a program, but I'm not sure if that's what you think or that your are worried about having threads mesh up with each other.


Coordinator
Dec 4, 2010 at 3:42 AM

scrabble:

I'm stuck on the ParseHumanReadable function in the Emulator Library (which I changed to ParseToFountainState). There are one of three packets that the server could send to the cRIO/eRIO, one of length two to set the north mister state, one of length ten to set the south end valves, and a "moron packet" of any other length that wasn't set up correctly :-P

No matter what we select as a return type (either your List<T> or the FountainState), we need to return a complete state that contains both north end and south end data, but the method will only be operating on a packet that contains data for one or the other.

It seems to me that the return value of that function would eventually be sent to SetState(...) to change the state of the fountain? To do this we need a complete state, but as it is we can't get one from the ParseWhatever function.

See the issue?

I'll keep digesting this and let you know if I think of any solutions, let me know if you have same.

 

Coordinator
Dec 4, 2010 at 3:42 AM

OK. Let's look at the different issues.

1. What to do with bad input?
Bad input occurs when the packet is the wrong size or contains the wrong magic numbers.
When the cRIO receives bad input, it does not modify the state. When you try to parse this, I would recommend returning null and not changing the state.
  

2. How do we return all of the data?

We know each packet doesn't contain all of the new state data, but we need to know and retain the unaffected states given by previous data. When you are updating the state, first call GetState() and then update the new fields. For example, when you get the new south end data, call GetState(), update only the south end vars, set the new state, and then return the new object.

For the return type, why don't you just use the FountainState? That better encapsulates OOP. For the indexes, use the enums in the Common Components library.

Coordinator
Dec 4, 2010 at 3:45 AM

scrabble:

1) is about what I was planning to do

2) duh. I'm not quite sure why I didn't think of that... when working on it today I even added a private FountainState to the ERIO class, thanks for that

I have changed your List<t>s to FountainState in my local copy, once I get some more done I'll check the code back in.