可以自己手动创建:继承 Service类 并重写onCreate()方法。也可以使用下图样子新建服务类,android studio创建服务自动回添加依赖秩序重写方法
onCreate()方法主要是提取保存的数据,添加寄存器,暂时不启动modbus监听线程.看一下代码:
// todo:0-499是非掉电存储区 500-999是掉电存储区
private boolean[] registe_0x=new boolean[500];//申请500个布尔变量作为0x区掉电存储缓冲地址(这部分变量是外部可读可写区)
// todo:0-499是非掉电存储区 500-999是掉电存储区
private int[] registe_4x=new int[500];//申请500个整数变量作为4x区掉电存储缓冲地址(这部分是可读可写区)
SimpleProcessImage modbus_data = null;
@Override
public void onCreate() {
super.onCreate();
Log.e("信息","开始创建modbus服务");
takeOutSaveData();//取出保存的数据
//创建500个非掉电存储区 0x数据
int i=0;
modbus_data = new SimpleProcessImage();
int abc=0;
for(i=0;i<500;i++){
modbus_data.addDigitalOut(new SimpleDigitalOut(false));//设置0x区
abc++;
}
//创建500个掉电存储区 0x数据
for(i=0;i<500;i++){
modbus_data.addDigitalOut(new SimpleDigitalOut(registe_0x[i]));
abc++;
}
/** 创建1X 数据 离散输入寄存器没有掉电存储区 */
for(i=0;i<1000;i++){
modbus_data.addDigitalIn(new SimpleDigitalIn(false));//设置0x区
}
/**创建3X数据 输入寄存器没有掉电存储区 */
for(i=0;i<1000;i++){
modbus_data.addInputRegister(new SimpleInputRegister(0));
}
/**创建4X 非掉电存储区 保持寄存器可读可写区*/
for(i=0;i<500;i++){
modbus_data.addRegister(new SimpleRegister(0));
}
//创建500个掉电存储区
for(i=0;i<500;i++){
modbus_data.addRegister(new SimpleRegister(registe_4x[i]));
}
ModbusCoupler.getReference().setProcessImage(modbus_data);
ModbusCoupler.getReference().setMaster(false);
ModbusCoupler.getReference().setUnitID(1);//设备地址
}
modbus监听服务开启后,check_data_handler()这个方法是校验外部存储区部分是否改变了如果改变了需要保存一下,防止突然掉电未做保存。
/**
* 运行网络通讯协议服务
* modbus服务运行
*
* @param setLocalIP 设置本地IP 设置本机IP地址(因为有可能多网卡运行所以需要设置本机IP运行)
* @param maxClient 最大的客户 最多允许多少客户端连接 默认3个
* @param port 端口 应该大于1024(因为1024以下的端口由android使用
*/
public void runModbusService(final String setLocalIP,final int maxClient,final int port ) {
if(!isRunner()){//如果没有连接则建立连接
new Thread(new Runnable() {
@Override
public void run() {
Log.e("信息","开始运行服务");
Log.e("信息","IP="+setLocalIP);
Log.e("信息","连接="+maxClient);
Log.e("信息","端口="+port);
try{
final InetAddress localIp=InetAddress.getByName(setLocalIP);
listener = new ModbusTCPListener(maxClient);//设置最大客户端连接
listener.setPort(port);//1024一下的端口是系统端口不能随便调用
listener.setAddress(localIp);
is_run=true;
listener.start();
check_data_handler.postDelayed(check_data_runable,1000);//1秒钟后开启检测数据是否改变
}catch (Exception e){
Log.e("信息",e.toString());
}
}
}).start();
}
}
/**
* Moudbus Tcp服务绑定
* @author 腾飞
* @date 2020/02/22
*/
public class MoudbusTcpServiceBinder extends Binder {
public MoudbusTcpService get_service(){
return MoudbusTcpService.this;
}
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
// throw new UnsupportedOperationException("Not yet implemented");
return new MoudbusTcpServiceBinder();
}
moudbus_connection=new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
moudbus_binder=(MoudbusTcpService.MoudbusTcpServiceBinder)service;
my_modbus_service=moudbus_binder.get_service();
String ip_addr=new IpAddress().getHostIp();
my_modbus_service.runModbusService(ip_addr,2,2000);
//测试服务是否正常(包含了一些测试代码)
Log.i("信息","dd"+my_modbus_service.get_0x_value(5));
Log.i("信息","dd"+my_modbus_service.get_0x_value(5,10));
Log.i("信息","dd"+my_modbus_service.get_1x_value(6));
Log.i("信息","dd"+my_modbus_service.get_1x_value(1,10));
Log.i("信息","dd"+my_modbus_service.get_3x_value(5));
Log.i("信息","dd"+my_modbus_service.get_3x_value(5,5));
Log.i("信息","dd"+my_modbus_service.get_4x_value(7));
Log.i("信息","dd"+my_modbus_service.get_4x_value(8,10));
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
Intent modbusIntent=new Intent(this,MoudbusTcpService.class);
startService(modbusIntent);//开启服务//必须先start否则如果切换activity后bingService自动卸载此服务,会造成服务不正常工作
bindService(modbusIntent,moudbus_connection,BIND_AUTO_CREATE);//自动绑定如果没有启动服务会自动启动服务
private final String MOUDBUS_STORAGE_NAME="modbus_unit01";//modbus存储区的名字
private final String STORAGE_0X_NAME="0x_storage";//0x存储区名字
/**
* 保存0 x数据
*/
private void save_0x_Data(){
JSONArray array_data=new JSONArray();
for(int i=0;i<500;i++){
array_data.put(registe_0x[i]);
}
SharedPreferences wp=getApplicationContext().getSharedPreferences(MOUDBUS_STORAGE_NAME,MODE_PRIVATE);//得到存储区的名字 如果没有则创建一个
SharedPreferences.Editor wp_edit=wp.edit();
wp_edit.putString(STORAGE_0X_NAME,array_data.toString());//存入
wp_edit.commit();//提交
}
/**
* 取出保存数据
*/
private void takeOutSaveData(){
SharedPreferences read_share=getApplicationContext().getSharedPreferences(MOUDBUS_STORAGE_NAME,MODE_PRIVATE);//得到存储区的名字 如果没有则创建一个
String storage_0x_list_str=read_share.getString(STORAGE_0X_NAME,"NULL");//获取0x区的存储的数据
String storage_4x_list_str=read_share.getString(STORAGE_4X_NAME,"NULL");//获取4x区的存储的数据
//尝试把字符串转换成bool数组
try{
JSONArray storage_0x_list = new JSONArray(storage_0x_list_str);
for (int i=0;i<storage_0x_list.length();i++){
registe_0x[i]=storage_0x_list.getBoolean(i);//获取布尔值
}
}catch (Exception e){
Log.i("信息",e.toString());
save_0x_Data();//初始化数据
//如果出错重新填入
}
//尝试把字符串转换成int数组
try{
JSONArray storage_4x_list = new JSONArray(storage_4x_list_str);
for (int i=0;i<storage_4x_list.length();i++){
registe_4x[i]=storage_4x_list.getInt(i);
}
}catch (Exception e){
Log.i("信息",e.toString());
save_4x_Data();//初始化4x区
//如果出错重新填入
}
}
/**
* 设置0 x值
* 0x区是一个可读可写的离散变量区
* 这部分区域可分为 掉电存储和掉电清零区
* 其中 寄存器地址0-499是非掉电存储区
* 寄存器地址500-999是掉电存储区
*
* @param registe_addr 寄存器地址
* @param bool_value bool值
*/
public void set_0x_value(int registe_addr,boolean bool_value){
modbus_data.setDigitalIn(registe_addr,new SimpleDigitalIn(bool_value));
}
/**
* 得到0 x值
*
* @param regist_addr 寄存器地址
* @return 当前地址的值
*/
public boolean get_0x_value(int regist_addr){
return modbus_data.getDigitalOut(regist_addr).isSet();
}
public ArrayList<Boolean> get_0x_value(int regist_addr,int count){
ArrayList<Boolean> data_array=new ArrayList<>(count);
for (int i=0;i<count;i++){
data_array.add(get_0x_value(regist_addr+i));
}
return data_array;
}