sailingYOLO - Hi,I'm trying to get engine run...

Hi, I'm trying to get engine runtime from my SignalK server ("propulsion.0.runTime") to my ESP running SensESP and displaying it on my e-paper display near the engine. I need both a timer based display update (SkListener?) and a on-demand based display update (button). I have a working display update function named "updateRunTime()", but I don't know how to get the data from SignalK server and then call that function. Even if I did, I don't know how to find out what datatype signalK is sending, can't find that in the data browser. I know the units is seconds. Using plugin "signalk-hour-meter" After pulling what hair I have left researching this for hours and hours I haven't found anything I can use to go forward with this. If you have anything that can help a beginner moving forward it would be much appreciated, sample code or anything, thanks!
7 Replies
Matti Airas
Matti Airas2w ago
You have a couple of different things here that you can tackle independently. First, you need to get the data sent. If you named your engine runtime path propulsion.0.runTime but don't have it in the data browser, for some reason the data isn't produced properly. That is the first thing to tackle. The value is a float, and the units are seconds. Once you have that sorted out, you can start looking into your SensESP code. Receiving and display update are different functions and it's better to keep them separate, especially because you have an e-paper display which you don't want to update every second. Receiving the data done with a FloatSKListener. This is a very simple example of how to do that: https://github.com/SignalK/SensESP/blob/main/examples/listener.cpp. Decoupling of the receiver and display updates can be done using a separate variable: you write the runtime value into a variable, and have an independent screen updates by calling your update function with onRepeat. The button handler can call the update function separately. Alternatively, you can keep everything within the realm of SensESP producers and consumers. In that case, you would put a Throttle transform between the listener and the output call to limit the number of updates. If you want to update the display even if the input stream goes silent, you can change that to RepeatConstantRate. You then call your update function with a LambdaConsumer that is connected to the repeating transform. To handle the button press, you could have a Filter transform that connects to the runTime listener (that produces values every second or so) and only transmits its value if a button press has been registered (indicated for example by a flag variable). This transform would be in parallel to the Throttle or RepeatConstantRate and would connect to the same LambdaConsumer update object.
sailingYOLO
sailingYOLOOP2w ago
Hi. Thanks for the comprehensive answer 👍 . Maybe I was unclear, I have everything working, SK data, Display update, Button events and actions to update on demand. I did also look at the example, previous of posting here, but I still don't understand how call a function from within the ->Connect_To function? Lambda? I want to update the display automagically every 30 minutes or so, that's configured in the Listener I guess. 1. How do I populate the value from a SK-path to a global variable? 2. How do I call a function from the Connect_To? Sorry for the misunderstanding, again, thank you for the previous answer!
Matti Airas
Matti Airas2w ago
Have a look at LambdaConsumer and the lambda tutorials. Lambdas are just functions with a fancy syntax; hence, LambdaConsumer takes the input and feeds it to a function. It doesn't even have to be a lambda; a pointer to a regular function works as well. In that function, you can assign the input to a variable or do any other shenanigans you want to.
sailingYOLO
sailingYOLOOP2w ago
Hi. Thanks again for the fast answer 🙂 Have looked into the chain counter example, but need to look some more. Still no clue how to read SignalK path from SensESP, anyone that can direct me to an example please.
onlytiebowline
There is a good example in https://github.com/mhaberler/SensESP-M5Stack/blob/main/src/main.cpp
const char* sk_gpsfix = "navigation.gnss.methodQuality";
auto* gpsfix = new StringSKListener(sk_gpsfix, listen_delay);
gpsfix->connect_to(new LambdaConsumer<String>([](String fix) {
M5.Lcd.setTextColor(YELLOW, BLACK);
M5.Lcd.setCursor(0, 80);
M5.Lcd.printf(" gpsfix: %s ", fix);
}));
const char* sk_gpsfix = "navigation.gnss.methodQuality";
auto* gpsfix = new StringSKListener(sk_gpsfix, listen_delay);
gpsfix->connect_to(new LambdaConsumer<String>([](String fix) {
M5.Lcd.setTextColor(YELLOW, BLACK);
M5.Lcd.setCursor(0, 80);
M5.Lcd.printf(" gpsfix: %s ", fix);
}));
sailingYOLO
sailingYOLOOP4d ago
Thank you, that worked great! Is there a way to get a SignalK value from the server on demand instead of getting events triggered every listen_delay?
onlytiebowline
Documentation says it "emits its value whenever it changes" and the listen_delay is the " minimum interval between updates in ms" https://signalk.org/SensESP/generated/docs/classsensesp_1_1_s_k_value_listener.html#details So it sounds like it is getting new values as it changes. You could test this out by setting a very long listed_day on your esp device and manually sending a new value on signal k Server > Data Fiddler

Did you find this page helpful?