Code Monkey home page Code Monkey logo

Comments (8)

bjoernbrings avatar bjoernbrings commented on September 14, 2024 1

Another example that helped me to understand the code was this

from rscp-e3dc-sample.

bvotteler avatar bvotteler commented on September 14, 2024

Hey @bjoernbrings ,

Thank you for the kind words!

I pretty much reverse engineered it from the C++ example. I had the good fortune that, back when I developed the first Java daemon for a client (around 2018), my client gave me full access to a PC that sat on the right network to interact with their E3DC machine. That helped me figure out what the inputs and outputs looked like. Also, the data the client wanted was almost fully covered by the example code, if I remember correctly. I didn't have to try out many other controls. And those that I did were only getters.

Warning: What follows is a wall of text. Hopefully somewhat coherent, but no guarantee. :)
It describes how I would go about finding the right structure for setters.

My best tips for exploring steering/control commands is to look at the RSCPTag constants.
I've deliberately grouped them the same way as they were in E3DC's original example. It seems they have structured them to have the requests and responses close together. e.g. TAG_<subsytem>_REQ_<something> for the request, and the corresponding collection of TAG_<subsystem>_<something> in the response.
The names usually match (ie. response has the same name minus the REQ bit), and at times there may be more values coming back - this usually means the first tag is a collection, and the ones following are contained in it with the "actual" values.
Finally, there often is a GET method to get a hint, or at least a safe way to explore likely inputs.

Whenever I explored a new command it took me some trial and error to figure out the inputs. But usually starting with any RSCP_DataType for the request that seems to make sense would work. And keep trying until I stop getting errors :)

Here is an example of how I'd try to figure out some input for a setter.
If I want to figure out how to set battery-to-car mode (and I really have no idea), this is the tag for it:
TAG_EMS_REQ_SET_BATTERY_TO_CAR_MODE with some data type - NONE, BOOL (true), UCHAR8 (mode number X) maybe? Not sure, but I could make a case for either, so I want to test it.
I then see if I can find a matching GET request. Sometimes it has a GET in the tag, sometimes it just lacks the SET in the tag. In this case it's close by (it usually is), and I want to test using:
TAG_EMS_REQ_BATTERY_TO_CAR_MODE... no SET, but has REQ, so probably a getter and I should be able to safely test with it - most likely taking a data type NONE, I would guess (if it really is a getter). The response for that will be TAG_EMS_BATTERY_TO_CAR_MODE and the data type of that response tag is almost certainly going to be the same as is expected for the request to set battery to car mode. I now can plug that into the request I started off with, TAG_EMS_REQ_SET_BATTERY_TO_CAR_MODE.

Final tip: Another resource I used to get a "feeling" for the data types in particular, was looking at their "E3DC ModBus-Dokumentation" - I hope you understand some German, or that documentation will be less useful. While it isn't the same as the RSCP protocol, it gave me some clues as to what the engineers used as go-to data types, such as lots of uint with varying byte lengths.
I think it is only available directly through E3DC's web portal, but I have had some luck finding it when searching Google, too. Let me know if you can't find it, and I can send you a copy.

Alright, this turned out much longer than I thought it would.
I hope this makes sense, and if not, do not hesitate to ask. I'm happy to share the little bit I've figured out so far.

Cheers,

Brendon

from rscp-e3dc-sample.

bvotteler avatar bvotteler commented on September 14, 2024

Also, just in case you missed it:
I have a sample project that uses this library to request history data from the database.

from rscp-e3dc-sample.

bjoernbrings avatar bjoernbrings commented on September 14, 2024

Hey Brendon,

thanks for your long answer. Very helpful for me was indeed the part about just putting some Bool value in the request as I was getting some error message as I was putting nothing in it (and there was no method for NONE).

Just in case anyone needs more sample material (that helps me usually a lot), the following query in the buildSampleRequestFrame method requests the current values

        RSCPData req1 = RSCPData.builder().tag(RSCPTag.TAG_EMS_REQ_POWER_PV).boolValue(true).build();
        RSCPData req2 = RSCPData.builder().tag(RSCPTag.TAG_EMS_REQ_POWER_BAT).boolValue(true).build();
        RSCPData req3 = RSCPData.builder().tag(RSCPTag.TAG_EMS_REQ_POWER_HOME).boolValue(true).build();
        RSCPData req4 = RSCPData.builder().tag(RSCPTag.TAG_EMS_REQ_POWER_GRID).boolValue(true).build();
        RSCPData req5 = RSCPData.builder().tag(RSCPTag.TAG_EMS_REQ_POWER_ADD).boolValue(true).build();
        RSCPData req6 = RSCPData.builder().tag(RSCPTag.TAG_EMS_REQ_EMERGENCY_POWER_STATUS).boolValue(true).build();
        RSCPData req7 = RSCPData.builder().tag(RSCPTag.TAG_EMS_REQ_AUTARKY).boolValue(true).build();
        RSCPData req8 = RSCPData.builder().tag(RSCPTag.TAG_EMS_REQ_BAT_SOC).boolValue(true).build();

        // build frame and append the request container
        RSCPFrame reqFrame = RSCPFrame.builder().timestamp(Instant.now()).addData(req1).addData(req2).addData(req3)
                .addData(req4).addData(req5).addData(req6).addData(req7).addData(req8).build();

        return reqFrame1.getAsByteArray();

Björn

from rscp-e3dc-sample.

bvotteler avatar bvotteler commented on September 14, 2024

thanks for your long answer. Very helpful for me was indeed the part about just putting some Bool value in the request as I was getting some error message as I was putting nothing in it (and there was no method for NONE).

Good point, I didn't provide an easy method for NONE. Good shout, and I'll cook up something for the next version.

Meanwhile, something like this should work to create a NONE:

RSCPData req1 = RSCPData.builder().tag(RSCPTag.TAG_EMS_REQ_POWER_PV).valueOfType(RSCPDataType.NONE, new byte[0]).build();

valueOfType(RSCPDataType, byte[]) was built with flexibility in mind - I have added the other options for brevity.

Hang on, I just realized that the validation will fail for a proper NONE with empty value. Yeah, that won't do. To be fixed.
Update: I raised the bug here.

from rscp-e3dc-sample.

bvotteler avatar bvotteler commented on September 14, 2024

Update: Fixed the NONE value issue in rscp-e3dc-lib version 1.0.1

Going forward, the following two ways of constructing a RSCPData instance holding NONE are equivalent:

RSCPData.builder().tag(RSCPTag.TAG_EMS_REQ_POWER_PV).valueOfType(RSCPDataType.NONE, new byte[0]).build();
// same as
RSCPData.builder().tag(RSCPTag.TAG_EMS_REQ_POWER_PV).noneValue().build();

from rscp-e3dc-sample.

bvotteler avatar bvotteler commented on September 14, 2024

@bjoernbrings just to clarify:
Did you try to send a NONE value and got an error from the server, or did you get the error constructing it when calling .build() (like I have observed)?

from rscp-e3dc-sample.

bjoernbrings avatar bjoernbrings commented on September 14, 2024

Thanks. It was just about the validation (and as I didn't have experience I didn't just want to bypass it ;))

from rscp-e3dc-sample.

Related Issues (1)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.