-
Notifications
You must be signed in to change notification settings - Fork 11
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
Guru mediditation #1
Comments
The delegate class WiThrottleDelegate is intended as an interface class designation, and some other class that does real work is expected to inherit from that interface class. Well, C++ uses inheritance for this, at least. I've been doing a lot of work in iOS development lately, and the delegate pattern is all over the place in their APIs. The point is that the WiThrottle protocol code does not know anything about what to do when various activities occur. Your code needs to do the right thing -- update a clock display, or show something on a UI screen for function state, etc. You pass in a reference to the controller class, which implements the delegate interface, and then the WiThrottle code will call code in the controller class (via that delegate interface) and your controller can do whatever it needs to. This keeps the WiThrottle class simple -- all it does it generic stream I/O, command parsing & creation, and delegate calling. It would be extremely rare to see an object of WiThrottleDelegate, or that doesn't do something else besides the WiThrottle delegate methods. I've not been doing much with this codebase, since my project that needs WiThrottle support is no longer based on the Arduino interfaces, and so the String & Stream classes aren't available to me anymore. I've got a newer (very similar) codebase that's a little more generic C++, which I'm using with the ESP32 IDF. So in Arduino land, you might have a ClockInterface class, which inherits from WiThrottleDelegate. The setup() function would create a clockInterface object, and then assign that into the wiThrottle.delegate member variable). Some code, maybe the clockInterface, maybe not, is responsible for the network setup and establishing that Stream and passing it into the WiThrottle parser. Each time you call check() [which should be A LOT], the WiThrottle code checks to see if there is any new data to read on that Stream, and if there is, it'll read it and try to form a command out of it. There's a buffer, so incomplete messages can be read and processed correctly. My new code doesn't even do the I/O itself, you don't call check() on it, you pass in the data that you read, so the parser is completely free of external I/O. (Yes, that parser only reads, sending commands is done in a different blob of code -- perhaps I ought to combine them again, and have a delegate method that takes a complete command and handles all of the I/O needed to send the data). [That'll go on my todo list]. |
Hi --
So, I would then define:
void receivedFunctionState(uint8_t func, bool state) {
Serial.print("\n Received a function update! ");
}
And then assign it to:
delegate->receivedFunctionState = receivedFunctionState;
Is that right?
Thanks
David
…On Mon, Jul 22, 2019 at 1:20 PM david d zuhn ***@***.***> wrote:
The delegate class WiThrottleDelegate is intended as an interface class
designation, and some other class that does real work is expected to
inherit from that interface class. Well, C++ uses inheritance for this, at
least. I've been doing a lot of work in iOS development lately, and the
delegate pattern is all over the place in their APIs.
The point is that the WiThrottle protocol code does not know anything
about what to do when various activities occur. Your code needs to do the
right thing -- update a clock display, or show something on a UI screen for
function state, etc. You pass in a reference to the controller class, which
implements the delegate interface, and then the WiThrottle code will call
code in the controller class (via that delegate interface) and your
controller can do whatever it needs to.
This keeps the WiThrottle class simple -- all it does it generic stream
I/O, command parsing & creation, and delegate calling.
It would be extremely rare to see an object of WiThrottleDelegate, or that
doesn't do something else besides the WiThrottle delegate methods.
I've not been doing much with this codebase, since my project that needs
WiThrottle support is no longer based on the Arduino interfaces, and so the
String & Stream classes aren't available to me anymore. I've got a newer
(very similar) codebase that's a little more generic C++, which I'm using
with the ESP32 IDF.
So in Arduino land, you might have a ClockInterface class, which inherits
from WiThrottleDelegate. The setup() function would create a clockInterface
object, and then assign that into the wiThrottle.delegate member variable).
Some code, maybe the clockInterface, maybe not, is responsible for the
network setup and establishing that Stream and passing it into the
WiThrottle parser. Each time you call check() [which should be A LOT], the
WiThrottle code checks to see if there is any new data to read on that
Stream, and if there is, it'll read it and try to form a command out of it.
There's a buffer, so incomplete messages can be read and processed
correctly.
My new code doesn't even do the I/O itself, you don't call check() on it,
you pass in the data that you read, so the parser is completely free of
external I/O. (Yes, that parser only reads, sending commands is done in a
different blob of code -- perhaps I ought to combine them again, and have a
delegate method that takes a complete command and handles all of the I/O
needed to send the data). [That'll go on my todo list].
—
You are receiving this because you modified the open/close state.
Reply to this email directly, view it on GitHub
<#1>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAEDQSWIM4UYUCXUMOA4P5LQAYI73ANCNFSM4IF4DHWA>
.
|
Nope. That's mixing functions & classes, and you can't do that. You can have a class like this: class ClockController : public WiThrottleDelegate void fastTimeChanged(uint32_t time) { } WiThrottle wiThrottle; void setup() { // do what you need to do in order to get a Stream, such as open a TCP socket to the server void loop() { Now, in reality, you probably need to implement your own loop inside of loop(), since the TCP socket may drop and you need to re-open it after setup() has been called. This is one of the reasons I abandoned the Arduino framework. Robust networking code is hard to do, and Arduino doesn't help you a whole lot. Simple stuff works okay, if you're willing to power-cycle to re-connect to the JMRI server. |
Note that what you wrote for receivedFunctionState and what I wrote look a lot alike, but one is part of a class and one is not. That's all the difference, since the delegate is a class (with defined methods). |
Thanks for the info. I will have a go at it.
David
…On Mon, Jul 22, 2019 at 2:54 PM david d zuhn ***@***.***> wrote:
Nope. That's mixing functions & classes, and you can't do that.
You can have a class like this:
class ClockController : public WiThrottleDelegate
{
void begin(int i2cAddr) { // do something to initialize the display at
i2cAddr, for example }
void receivedFunctionState(uint8_t func, bool state) {
Serial.print("\n Received a function update! ");
// now use the clock display at i2cAddr to display the function state you
just received
}
void fastTimeChanged(uint32_t time) {
// now display the new time that you've just been given
}
}
WiThrottle wiThrottle;
ClockController clockController;
void setup() {
clockController.begin(0x70);
wiThrottle.delegate = clockController;
// do what you need to do in order to get a Stream, such as open a TCP
socket to the server
wiThrottle.begin(stream);
}
void loop() {
wiThrottle.check();
}
Now, in reality, you probably need to implement your own loop inside of
loop(), since the TCP socket may drop and you need to re-open it after
setup() has been called. This is one of the reasons I abandoned the Arduino
framework. Robust networking code is hard to do, and Arduino doesn't help
you a whole lot. Simple stuff works okay, if you're willing to power-cycle
to re-connect to the JMRI server.
—
You are receiving this because you modified the open/close state.
Reply to this email directly, view it on GitHub
<#1>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAEDQSTCS3SRL3OGXHCAP5TQAYUABANCNFSM4IF4DHWA>
.
|
Hi --
I tried you FastClock example, and adapted it for an OLED display. However, it kept crashing. I think the problem boiled down to a missing wiThrottle.begin(&Serial) in:
void wifiOnConnect() {
...
Serial.println("connected succeeded");
wiThrottle.begin(&Serial);
wiThrottle.connect(&client);
...
}
Also, I had to comment out:
// if (wiThrottle.protocolVersionChanged) {
// Serial.print("PROTOCOL VERSION "); Serial.println(wiThrottle.protocolVersion);
// }
I think you moved that into the delegation class.
I do have a question, though. How does one program the delegation routines, or rather 'connect' them to the class WiThrottleDelegate? Do I need to subclass that? Or just write WiThrottleDelegate::receivedSpeed(int speed) { }, for example?
Thanks
David
The text was updated successfully, but these errors were encountered: