Giter VIP home page Giter VIP logo

modbus4android's Introduction

Modbus4Android

Modbus的Android实现,添加对Android串口(RTU)的支持

APP TCP

不了解Modbus的,可以阅读一下 MODBUS通讯协议

参考

https://github.com/infiniteautomation/modbus4j

https://github.com/zgkxzx/Modbus4Android

使用

添加依赖

allprojects {
  repositories {
    ...
    maven { url 'https://jitpack.io' }
  }
}

  dependencies {
    implementation('com.github.licheedev:Modbus4Android:3.0.0') {
        // 解决"commons-logging"冲突问题
        exclude group: 'commons-logging', module: 'commons-logging'
    }
}
<manifest ...>
    <application ...>
        <!-- 解决"commons-logging"冲突问题 -->
        <uses-library android:name="org.apache.http.legacy" android:required="false" />
    </application>
</manifest>

创建管理类单例

public class ModbusManager extends ModbusWorker {

    private static volatile ModbusManager sInstance;

    public static ModbusManager get() {
        ModbusManager manager = sInstance;
        if (manager == null) {
            synchronized (ModbusManager.class) {
                manager = sInstance;
                if (manager == null) {
                    manager = new ModbusManager();
                    sInstance = manager;
                }
            }
        }
        return manager;
    }

    private ModbusManager() {
    }

    /**
     * 释放整个ModbusManager,单例会被置null
     */
    public synchronized void release() {
        super.release();
        sInstance = null;
    }
}

开启设备

ModbusParam param;

if (mMode == MODE_SERIAL) {
    // 串口
    String path = mDevicePaths[mDeviceIndex];
    int baudrate = mBaudrates[mBaudrateIndex];

    mDeviceConfig.updateSerialConfig(path, baudrate);
    param = SerialParam.create(path, baudrate) // 串口地址和波特率
        .setDataBits(mDataBits) // 数据位
        .setParity(mParity) // 校验位
        .setStopBits(mStopBits) // 停止位
        .setTimeout(1000).setRetries(0); // 不重试
} else {
    // TCP
    String host = mEtHost.getText().toString().trim();
    int port = 0;
    try {
        port = Integer.parseInt(mEtPort.getText().toString().trim());
    } catch (NumberFormatException e) {
        //e.printStackTrace();
    }
    param = TcpParam.create(host, port)
        .setTimeout(1000)
        .setRetries(0)
        .setEncapsulated(false)
        .setKeepAlive(true);
}

ModbusManager.get().closeModbusMaster(); // 先关闭一下
ModbusManager.get().init(serialParam, new ModbusCallback<ModbusMaster>() {
    @Override
    public void onSuccess(ModbusMaster modbusMaster) {
        showOneToast("打开成功");
    }

    @Override
    public void onFailure(Throwable tr) {
        showOneToast("打开失败");
    }

    @Override
    public void onFinally() {
        // todo updateDeviceSwitchButton();
    }
});

可选配置

// 启用rtu的crc校验(默认就启用)
ModbusConfig.setEnableRtuCrc(true);
// 打印数据log(默认全禁用)
// System.out: MessagingControl.send: 01030000000305cb
// System.out: MessagingConnection.read: 010306000100020000bd75
ModbusConfig.setEnableDataLog(true, true);

功能码操作示例

普通用法

// 普通写法
ModbusManager.get()
    .readHoldingRegisters(mSalveId, mOffset, mAmount,
        new ModbusCallback<ReadHoldingRegistersResponse>() {
            @Override
            public void onSuccess(
                ReadHoldingRegistersResponse readHoldingRegistersResponse) {
                byte[] data = readHoldingRegistersResponse.getData();
                mTvConsole.append("F03读取:" + ByteUtil.bytes2HexStr(data) + "\n");
            }

            @Override
            public void onFailure(Throwable tr) {
                appendError("F03", tr);
            }

            @Override
            public void onFinally() {

            }
        });

其他功能码的用法,可以参考Demo的MainActivity.java

RxJava用法(2.0,其他版本按需修改)

复制rxjava相关文件到自己的项目中

// 修改实现方式
//public class ModbusManager extends ModbusWorker {}
public class ModbusManager extends RxModbusWorker {}

// Rx写法
ModbusManager.get()
    .rxReadHoldingRegisters(mSalveId, mOffset, mAmount)
    .observeOn(AndroidSchedulers.mainThread())
    .compose(this.<ReadHoldingRegistersResponse>bindUntilEvent(ActivityEvent.DESTROY))
    .subscribe(new ModbusObserver<ReadHoldingRegistersResponse>() {
        @Override
        public void onSuccess(
            ReadHoldingRegistersResponse readHoldingRegistersResponse) {
            byte[] data = readHoldingRegistersResponse.getData();
            mTvConsole.append("F03读取:" + ByteUtil.bytes2HexStr(data) + "\n");
        }

        @Override
        public void onFailure(Throwable tr) {
            appendError("F03", tr);
        }
    });

Kotlin协程用法

复制ModbusWorkers.kt文件到自己的项目中

// 协程写法
lifecycleScope.launch {
    try {
        val response =
            ModbusManager.get().awaitReadHoldingRegisters(mSalveId, mOffset, mAmount)
        val data: ByteArray = response.data
        appendText("F03读取:" + ByteUtil.bytes2HexStr(data) + "\n")
    } catch (e: Exception) {
        appendError("F03", e)
    }
}

截图

F01 F02 F03 F04 F05 F06 F15 F16

modbus4android's People

Contributors

licheedev avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

modbus4android's Issues

请教一个问题啊

请问您这个库可以直接集成到商用项目里面吗?最近任务太赶了,没空调研了,如果稳定可用的话,我就用您这个直接集成进去了哈?

还有,我想问问,这个modbus-rtu,跟我写的一个串口通信,有什么区别吗,串口通信直接发“01060300014B2C”这样的指令。您这个库,是不是底层还是串口通信,但是上层通过modbus协议的规约,把参数也是转化成指令,通过串口发送吗?

老哥,读取数据的时候直接TimeOut了。。。

    private void Read(int ID, int ADDRESS, int COUNT)
    {
        if (ADDRESS == Integer.MIN_VALUE)
        {
            Toast.makeText(gContext, "Invalid Address", Toast.LENGTH_SHORT).show();
        }
        else
        {
            gModbusWorker.readHoldingRegisters(ID, ADDRESS, COUNT, new ModbusCallback<ReadHoldingRegistersResponse>() {
                @Override
                public void onSuccess(ReadHoldingRegistersResponse readHoldingRegistersResponse) {
                    byte[] data = readHoldingRegistersResponse.getData();
                    String result = new String(data, StandardCharsets.UTF_8);
                    Toast.makeText(gContext, result, Toast.LENGTH_SHORT).show();
                }

                @Override
                public void onFailure(Throwable tr) {
                    Toast.makeText(gContext, tr.getMessage(), Toast.LENGTH_SHORT).show();
                    Log.e("READ", tr.getMessage());
                }

                @Override
                public void onFinally() {
                }
            });
        }
    }

2021-04-12 11:07:56.937 3143-3143/com.zeroid.test E/READ: com.serotonin.modbus4j.sero.messaging.TimeoutException: request=SerialMessage [modbusMessage=ReadHoldingRegistersRequest [slaveId=1, getFunctionCode()=3, toString()=ReadNumericRequest [startOffset=200, numberOfRegisters=10]]]

谢谢大哥,请问有没有JAR Lib?

我不擅长Android Studio,结果直接下载,直接compile出出错了。感觉应该是dependancy的问题。
翻了其他网发现我应该太过时了。。。(20年)结果我就只会直接导入jar的方法。
不会什么Maven和Gradle的方法。
不知道是否能帮个忙,弄个jar方便一下。谢谢。

总是报错怎么解决?

image
代码下载后运行测试,总是走失败的回调,并且报这个错,是怎么回事啊?求解答!

每隔5秒发送一次指令去读取数据,一段时间后IO出错

每隔5秒发送一次指令去读取数据,一段时间后IO出错

java.io.IOException: I/O error
 W/System.err:     at java.io.FileInputStream.available0(Native Method)
 W/System.err:     at java.io.FileInputStream.available(FileInputStream.java:323)
 W/System.err:     at java.io.BufferedInputStream.available(BufferedInputStream.java:399)
 W/System.err:     at com.serotonin.modbus4j.sero.messaging.InputStreamListener.run(InputStreamListener.java:91)
 W/System.err:     at java.lang.Thread.run(Thread.java:761)

读取问题

循环读取,每隔50ms读取一次,会报com.serotonin.modbus4j.sero.messaging.WaitingRoomException: No recipient was found waiting for response for key com.serotonin.modbus4j.serial.SerialWaitingRoomKeyFactory$Sync 和 java.io.IOException: Bad file descriptor

OOM了老哥,求助

java.lang.OutOfMemoryError: pthread_create (stack size 16384 bytes) failed: Try again
at java.lang.VMThread.create(Native Method)
at java.lang.Thread.start(Thread.java:1029)
at java.util.concurrent.ThreadPoolExecutor.addWorker(ThreadPoolExecutor.java:920)
at java.util.concurrent.ThreadPoolExecutor.ensurePrestart(ThreadPoolExecutor.java:1553)
at java.util.concurrent.ScheduledThreadPoolExecutor.delayedExecute(ScheduledThreadPoolExecutor.java:306)
at java.util.concurrent.ScheduledThreadPoolExecutor.schedule(ScheduledThreadPoolExecutor.java:519)
at java.util.concurrent.ScheduledThreadPoolExecutor.submit(ScheduledThreadPoolExecutor.java:618)
at io.reactivex.internal.schedulers.NewThreadWorker.scheduleActual(NewThreadWorker.java:145)
at io.reactivex.internal.schedulers.IoScheduler$EventLoopWorker.schedule(IoScheduler.java:239)
at io.reactivex.Scheduler.scheduleDirect(Scheduler.java:203)
at io.reactivex.Scheduler.scheduleDirect(Scheduler.java:179)
at io.reactivex.internal.operators.observable.ObservableSubscribeOn.subscribeActual(ObservableSubscribeOn.java:36)
at io.reactivex.Observable.subscribe(Observable.java:12268)
at io.reactivex.internal.operators.observable.ObservableObserveOn.subscribeActual(ObservableObserveOn.java:45)
at io.reactivex.Observable.subscribe(Observable.java:12268)
at io.reactivex.internal.operators.observable.ObservableDoFinally.subscribeActual(ObservableDoFinally.java:43)
at io.reactivex.Observable.subscribe(Observable.java:12268)
at com.licheedev.modbus4android.ModbusWorker.subscribe(ModbusWorker.java:248)
at com.licheedev.modbus4android.ModbusWorker.readHoldingRegisters(ModbusWorker.java:604)
at com.zgkx.change.serialport.ElectricityMeterManager.startGetEMInfo(ElectricityMeterManager.kt:109)
at com.zgkx.change.serialport.ElectricityMeterManager$startGetEMInfo$11.run(ElectricityMeterManager.kt:226)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at com.zgkx.change.util.FreeThread$1.run(FreeThread.kt:25)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.os.HandlerThread.run(HandlerThread.java:61)
以下是代码
` SerialPortManager.readHoldingRegisters(SerialPortManager.slaveId, Integer.parseInt("2006", 16), 2,
object : ModbusCallback {
override fun onSuccess(readHoldingRegistersResponse: ReadHoldingRegistersResponse) {
val data = readHoldingRegistersResponse.data
Ua = HexUtils.byteArrayToFloat(data) / 10f
DevBean.INV = Ua.toString()
XLogUtil.log(TAG, "Ua-onSuccess:u=${Ua},data=${HexUtils.bytesToHexString(data)}")
}

                    override fun onFailure(tr: Throwable) {
                        XLogUtil.log(TAG, "Ua-onFailure\n$tr")
                        tr.printStackTrace()
                    }

                    override fun onFinally() {
                        XLogUtil.log(TAG, "Ua-onFinally")
                    }
                })`

怎么获取设备的串口号呢?

大神,我用Modbus Salve模拟了串口,但是为什么我在模拟器运行程序后,发现串口列表为空呢?
image

image
代码在这里就获取不到串口了

怎么使用rtu传参

您好,我现在收到一份modbus文档(rtu,rs485),如下:
image
查看您写的api,我不清楚这3个参数该如何对应:
// 普通写法
ModbusManager.get()
.readHoldingRegisters(mSalveId, mOffset, mAmount,
new ModbusCallback() {
@OverRide
public void onSuccess(
ReadHoldingRegistersResponse readHoldingRegistersResponse) {
byte[] data = readHoldingRegistersResponse.getData();
mTvConsole.append("F03读取:" + ByteUtil.bytes2HexStr(data) + "\n");
}

        @Override
        public void onFailure(Throwable tr) {
            appendError("F03", tr);
        }

        @Override
        public void onFinally() {

        }
    });

其中的mSalveId, mOffset, mAmount怎么对应到我的文档之上,烦请大神解答一下,不胜感激。

bindUntilEvent 是来自哪里的?

// Rx写法
ModbusManager.get()
.rxReadHoldingRegisters(mSalveId, mOffset, mAmount)
.observeOn(AndroidSchedulers.mainThread())
.compose(this.bindUntilEvent(ActivityEvent.DESTROY))
.subscribe(new ModbusObserver() {
@OverRide
public void onSuccess(
ReadHoldingRegistersResponse readHoldingRegistersResponse) {
byte[] data = readHoldingRegistersResponse.getData();
mTvConsole.append("F03读取:" + ByteUtil.bytes2HexStr(data) + "\n");
}

    @Override
    public void onFailure(Throwable tr) {
        appendError("F03", tr);
    }
});

error: cannot find symbol
.compose(this.bindUntilEvent(ActivityEvent.DESTROY))
^
symbol: method bindUntilEvent(ActivityEvent)

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.