Skip to content
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

Feature: GenericService #64

Open
tlf30 opened this issue May 8, 2023 · 3 comments
Open

Feature: GenericService #64

tlf30 opened this issue May 8, 2023 · 3 comments

Comments

@tlf30
Copy link

tlf30 commented May 8, 2023

Hello,
First, thank you for this amazing library.

It would be very helpful to have a GenericService class, where the service code can be provided in the constructor.
Something like this:

public class GenericService implements CipService<ByteBuf> {

    private final EPath.PaddedEPath requestPath;
    private final int serviceCode;

    public GenericService(int serviceCode, EPath.PaddedEPath requestPath) {
        this.requestPath = requestPath;
        this.serviceCode = serviceCode;
    }

    @Override
    public void encodeRequest(ByteBuf buffer) {
        MessageRouterRequest request = new MessageRouterRequest(
                serviceCode,
                requestPath,
                byteBuf -> {
                }
        );

        MessageRouterRequest.encode(request, buffer);
    }

    @Override
    public ByteBuf decodeResponse(ByteBuf buffer) throws CipResponseException {
        MessageRouterResponse response = MessageRouterResponse.decode(buffer);

        if (response.getGeneralStatus() == 0x00) {
            return response.getData();
        } else {
            ReferenceCountUtil.release(response.getData());

            throw new CipResponseException(response.getGeneralStatus(), response.getAdditionalStatus());
        }
    }
}

Thank you,
Trevor

@tlf30
Copy link
Author

tlf30 commented May 9, 2023

To add to this, a version that also accepts a ByteBuf for the source buffer as a generic solution would also be great.

@kevinherron
Copy link
Contributor

Noted. In the meantime there's nothing stopping your project from having a CipService implementation like this, right?

@tlf30
Copy link
Author

tlf30 commented May 9, 2023

Yep, this is my current implementation (which is somewhat specific to how my project moves data around):

package io.tlf.cip.tool.cip;

import com.digitalpetri.enip.cip.CipResponseException;
import com.digitalpetri.enip.cip.epath.EPath;
import com.digitalpetri.enip.cip.services.CipService;
import com.digitalpetri.enip.cip.structs.MessageRouterRequest;
import com.digitalpetri.enip.cip.structs.MessageRouterResponse;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.util.ReferenceCountUtil;

public class GenericService implements CipService<ByteBuf> {

    private final EPath.PaddedEPath requestPath;
    private final int serviceCode;
    private final byte[] requestData;
    private final MessageStruct requestStruct;

    public GenericService(int serviceCode, EPath.PaddedEPath requestPath) {
        this.requestPath = requestPath;
        this.serviceCode = serviceCode;
        this.requestData = null;
        this.requestStruct = null;
    }


    public GenericService(int serviceCode, EPath.PaddedEPath requestPath, byte[] requestData) {
        this.requestPath = requestPath;
        this.serviceCode = serviceCode;
        this.requestData = requestData;
        this.requestStruct = null;
    }

    public GenericService(int serviceCode, EPath.PaddedEPath requestPath, MessageStruct requestStruct) {
        this.requestPath = requestPath;
        this.serviceCode = serviceCode;
        this.requestData = null;
        this.requestStruct = requestStruct;
    }

    @Override
    public void encodeRequest(ByteBuf buffer) {
        MessageRouterRequest request = new MessageRouterRequest(
                serviceCode,
                requestPath,
                byteBuf -> {
                    if (requestData != null && requestData.length > 0) {
                        byteBuf.writeBytes(requestData);
                    } else if (requestStruct != null) {
                        requestStruct.encode(byteBuf);
                    }
                }
        );

        MessageRouterRequest.encode(request, buffer);
    }

    @Override
    public ByteBuf decodeResponse(ByteBuf buffer) throws CipResponseException {
        MessageRouterResponse response = MessageRouterResponse.decode(buffer);

        if (response.getGeneralStatus() == 0x00) {
            return response.getData();
        } else {
            ReferenceCountUtil.release(response.getData());

            throw new CipResponseException(response.getGeneralStatus(), response.getAdditionalStatus());
        }
    }
}

I just figured that something generic would be nice to have for others.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants