parent
0022e22f93
commit
7f43b90147
14 changed files with 428 additions and 9 deletions
@ -0,0 +1,18 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" |
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
||||
<parent> |
||||
<artifactId>lab-service-api</artifactId> |
||||
<groupId>org.springblade</groupId> |
||||
<version>2.8.1.RELEASE</version> |
||||
</parent> |
||||
<modelVersion>4.0.0</modelVersion> |
||||
|
||||
<artifactId>lab-iot-api</artifactId> |
||||
<name>${project.artifactId}</name> |
||||
<version>${bladex.project.version}</version> |
||||
<packaging>jar</packaging> |
||||
|
||||
|
||||
</project> |
||||
@ -0,0 +1,63 @@ |
||||
/* |
||||
* Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions are met: |
||||
* |
||||
* Redistributions of source code must retain the above copyright notice, |
||||
* this list of conditions and the following disclaimer. |
||||
* Redistributions in binary form must reproduce the above copyright |
||||
* notice, this list of conditions and the following disclaimer in the |
||||
* documentation and/or other materials provided with the distribution. |
||||
* Neither the name of the dreamlu.net developer nor the names of its |
||||
* contributors may be used to endorse or promote products derived from |
||||
* this software without specific prior written permission. |
||||
* Author: Chill 庄骞 (smallchill@163.com) |
||||
*/ |
||||
package org.springblade.iot.entry; |
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField; |
||||
import com.baomidou.mybatisplus.annotation.TableName; |
||||
import com.fasterxml.jackson.annotation.JsonFormat; |
||||
import io.swagger.annotations.ApiModel; |
||||
import io.swagger.annotations.ApiModelProperty; |
||||
import lombok.Data; |
||||
import lombok.EqualsAndHashCode; |
||||
import org.springblade.core.mp.base.BaseEntity; |
||||
import org.springframework.format.annotation.DateTimeFormat; |
||||
|
||||
import java.time.LocalDateTime; |
||||
|
||||
/** |
||||
* 数采配置实体类 |
||||
* |
||||
* @author swj |
||||
* @since 2022年8月17日16:29:15 |
||||
*/ |
||||
@Data |
||||
@TableName("t_sensor_base") |
||||
@EqualsAndHashCode(callSuper = true) |
||||
@ApiModel(value = "Sensor对象", description = "数采配置") |
||||
public class Sensor extends BaseEntity { |
||||
|
||||
@ApiModelProperty(value = "传感器名称") |
||||
private String name; |
||||
|
||||
@ApiModelProperty(value = "plc设备的ip") |
||||
private String ip; |
||||
|
||||
@ApiModelProperty(value = "信息名称(如:302更衣室压差)") |
||||
private String signalName; |
||||
|
||||
@ApiModelProperty(value = "数据类型(REAL->float)") |
||||
private String dataType; |
||||
|
||||
@ApiModelProperty(value = "寄存器地址") |
||||
private String registerAddress; |
||||
|
||||
@TableField(exist = false) |
||||
@ApiModelProperty(value = "单前的实时数据") |
||||
private String currData; |
||||
|
||||
private static final long serialVersionUID = 1L; |
||||
} |
||||
@ -0,0 +1,23 @@ |
||||
|
||||
package org.springblade.iot; |
||||
|
||||
import org.springblade.common.constant.LauncherConstant; |
||||
import org.springblade.core.cloud.feign.EnableBladeFeign; |
||||
import org.springblade.core.launch.BladeApplication; |
||||
import org.springframework.cloud.client.SpringCloudApplication; |
||||
|
||||
/** |
||||
* Iot启动器 |
||||
* @author swj |
||||
* @date 2022年8月17日15:21:251 |
||||
*/ |
||||
@EnableBladeFeign |
||||
@SpringCloudApplication |
||||
public class IotApplication { |
||||
|
||||
public static void main(String[] args) { |
||||
BladeApplication.run(LauncherConstant.APPLICATION_IOT_NAME, IotApplication.class, args); |
||||
} |
||||
|
||||
} |
||||
|
||||
@ -0,0 +1,88 @@ |
||||
|
||||
package org.springblade.iot.controller; |
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
||||
import com.baomidou.mybatisplus.core.metadata.IPage; |
||||
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport; |
||||
import io.swagger.annotations.Api; |
||||
import io.swagger.annotations.ApiOperation; |
||||
import io.swagger.annotations.ApiParam; |
||||
import lombok.AllArgsConstructor; |
||||
import org.springblade.core.boot.ctrl.BladeController; |
||||
import org.springblade.core.mp.support.Condition; |
||||
import org.springblade.core.mp.support.Query; |
||||
import org.springblade.core.secure.utils.AuthUtil; |
||||
import org.springblade.core.tool.api.R; |
||||
import org.springblade.core.tool.utils.Func; |
||||
import org.springblade.iot.entry.Sensor; |
||||
import org.springblade.iot.service.ISensorService; |
||||
import org.springframework.web.bind.annotation.*; |
||||
|
||||
import java.util.Date; |
||||
|
||||
/** |
||||
* 物品申领表 控制器 |
||||
* |
||||
* @author swj |
||||
* @since 2022年8月17日16:35:34 |
||||
*/ |
||||
@RestController |
||||
@AllArgsConstructor |
||||
@RequestMapping("/sensor") |
||||
@Api(value = "", tags = "") |
||||
public class SensorController extends BladeController { |
||||
|
||||
private final ISensorService service; |
||||
|
||||
/** |
||||
* 分页 |
||||
*/ |
||||
@GetMapping("/list") |
||||
@ApiOperationSupport(order = 2) |
||||
public R<Object> list(Sensor entry, Query query) { |
||||
LambdaQueryWrapper<Sensor> wrapper = new LambdaQueryWrapper<>(); |
||||
wrapper.orderByDesc(Sensor::getCreateTime); |
||||
IPage<Sensor> page = service.page(Condition.getPage(query), wrapper); |
||||
return R.data(page); |
||||
} |
||||
|
||||
/** |
||||
* 更改 |
||||
*/ |
||||
@PostMapping("/update") |
||||
@ApiOperation(value = "更改", notes = "更改") |
||||
public R update(@RequestBody Sensor entry) { |
||||
return R.data(service.updateById(entry)); |
||||
} |
||||
|
||||
/** |
||||
* 新增 |
||||
*/ |
||||
@PostMapping("/insert") |
||||
@ApiOperation(value = "新增", notes = "新增") |
||||
public R insert(@RequestBody Sensor entry) { |
||||
entry.setCreateTime(new Date()); |
||||
entry.setUpdateTime(new Date()); |
||||
entry.setCreateUser(AuthUtil.getUserId()); |
||||
entry.setUpdateUser(AuthUtil.getUserId()); |
||||
return R.data(service.save(entry)); |
||||
} |
||||
|
||||
/** |
||||
* 删除 |
||||
*/ |
||||
@PostMapping("/deleteByIds") |
||||
@ApiOperation(value = "逻辑删除", notes = "传入ids") |
||||
public R deleteByIds(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) { |
||||
return R.status(service.deleteLogic(Func.toLongList(ids))); |
||||
} |
||||
|
||||
/** |
||||
* 根据id获取对应的Sensor |
||||
*/ |
||||
@GetMapping("/getSensor") |
||||
public Sensor getReagent(String id) { |
||||
Sensor sensor = service.getById(id); |
||||
return sensor; |
||||
} |
||||
} |
||||
@ -0,0 +1,15 @@ |
||||
|
||||
package org.springblade.iot.mapper; |
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
||||
import org.springblade.iot.entry.Sensor; |
||||
|
||||
/** |
||||
* |
||||
* |
||||
* @author swj |
||||
* @since 2022年8月17日16:37:29 |
||||
*/ |
||||
public interface SensorMapper extends BaseMapper<Sensor> { |
||||
|
||||
} |
||||
@ -0,0 +1,13 @@ |
||||
|
||||
package org.springblade.iot.service; |
||||
|
||||
|
||||
import org.springblade.core.mp.base.BaseService; |
||||
import org.springblade.iot.entry.Sensor; |
||||
|
||||
/** |
||||
* @author swj |
||||
* @since 2022年8月17日16:39:35 |
||||
*/ |
||||
public interface ISensorService extends BaseService<Sensor> { |
||||
} |
||||
@ -0,0 +1,22 @@ |
||||
|
||||
package org.springblade.iot.service.impl; |
||||
|
||||
|
||||
import lombok.AllArgsConstructor; |
||||
import org.springblade.core.mp.base.BaseServiceImpl; |
||||
import org.springblade.iot.entry.Sensor; |
||||
import org.springblade.iot.mapper.SensorMapper; |
||||
import org.springblade.iot.service.ISensorService; |
||||
import org.springframework.stereotype.Service; |
||||
|
||||
|
||||
/** |
||||
* @author swj |
||||
* @since 2022年8月17日16:39:58 |
||||
*/ |
||||
@Service |
||||
@AllArgsConstructor |
||||
public class SensorServiceImpl extends BaseServiceImpl<SensorMapper, Sensor> implements ISensorService { |
||||
|
||||
private final SensorMapper sensorMapper; |
||||
} |
||||
@ -0,0 +1,120 @@ |
||||
package org.springblade.iot.utils; |
||||
|
||||
import com.serotonin.modbus4j.ModbusFactory; |
||||
import com.serotonin.modbus4j.ModbusMaster; |
||||
import com.serotonin.modbus4j.exception.ModbusInitException; |
||||
import com.serotonin.modbus4j.exception.ModbusTransportException; |
||||
import com.serotonin.modbus4j.ip.IpParameters; |
||||
import com.serotonin.modbus4j.msg.ReadHoldingRegistersRequest; |
||||
import com.serotonin.modbus4j.msg.ReadHoldingRegistersResponse; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
|
||||
/** |
||||
* @author swj |
||||
*/ |
||||
public class ReadModBusUtil { |
||||
|
||||
static ModbusFactory modbusFactory; |
||||
|
||||
static { |
||||
if (modbusFactory == null) { |
||||
modbusFactory = new ModbusFactory(); |
||||
} |
||||
} |
||||
|
||||
public static void main(String[] args) throws InterruptedException { |
||||
// 1.获取tcp协议的主机(上位机)
|
||||
ModbusMaster master = getTcpMaster("192.168.1.217", 502, 1); |
||||
// 2.初始化
|
||||
try { |
||||
master.init(); |
||||
while (0 == 0) { |
||||
// 3.读取保持寄存器数据
|
||||
readHoldingRegistersTest(master, 1, 0, 10); |
||||
Thread.sleep(1000L); |
||||
} |
||||
} catch (ModbusInitException e) { |
||||
e.printStackTrace(); |
||||
} finally { |
||||
// 销毁连接
|
||||
master.destroy(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 2 |
||||
*/ |
||||
public static ModbusMaster getTcpMaster(String ip, int port, int salveId) { |
||||
IpParameters params = new IpParameters(); |
||||
params.setHost(ip); |
||||
if (port == 0) { |
||||
params.setPort(502); |
||||
} else { |
||||
params.setPort(port); |
||||
} |
||||
ModbusMaster tcpMaster = modbusFactory.createTcpMaster(params, true); |
||||
return tcpMaster; |
||||
} |
||||
|
||||
/** |
||||
* 3.读取保持寄存器上的内容 |
||||
* |
||||
* @param master 主站 |
||||
* @param slaveId 从站地址 |
||||
* @param start 起始地址的偏移量 |
||||
* @param len 待读寄存器的个数 |
||||
*/ |
||||
private static void readHoldingRegistersTest(ModbusMaster master, int slaveId, int start, int len) { |
||||
try { |
||||
ReadHoldingRegistersRequest request = new ReadHoldingRegistersRequest(slaveId, start, len); |
||||
ReadHoldingRegistersResponse response = (ReadHoldingRegistersResponse) master.send(request); |
||||
if (response.isException()) { |
||||
System.out.println("Exception response: message=" + response.getExceptionMessage()); |
||||
} else { |
||||
byte[] data = response.getData(); |
||||
List<Float> floats = byteArrayToFloatList(data); |
||||
System.out.println("floats:" + floats); |
||||
} |
||||
} catch (ModbusTransportException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 4.将byte类型的arr转换成float |
||||
*/ |
||||
public static List<Float> byteArrayToFloatList(byte[] bytes){ |
||||
// index:0 1 2 3
|
||||
// byte:1-2 3-4 5-6 7-8
|
||||
// byte:2-1 4-3 6-5 8-7
|
||||
// 高低位转换操作:同一
|
||||
for (int i = 0; i < bytes.length; i++) { |
||||
if (i + 1 < bytes.length && i % 2 == 0) { |
||||
byte temp = bytes[i]; |
||||
bytes[i] = bytes[i + 1]; |
||||
bytes[i + 1] = temp; |
||||
} |
||||
} |
||||
List<Float> d = new ArrayList<>(bytes.length / 8); |
||||
byte[] doubleBuffer = new byte[4]; |
||||
for(int j = 0; j < bytes.length; j += 4) { |
||||
System.arraycopy(bytes, j, doubleBuffer, 0, doubleBuffer.length); |
||||
d.add(bytes2Float(doubleBuffer)); |
||||
} |
||||
return d; |
||||
} |
||||
|
||||
/** |
||||
* 5.将byte数组数据转换成float |
||||
*/ |
||||
public static float bytes2Float(byte[] arr) { |
||||
int accum = 0; |
||||
accum = accum|(arr[0] & 0xff) << 0; |
||||
accum = accum|(arr[1] & 0xff) << 8; |
||||
accum = accum|(arr[2] & 0xff) << 16; |
||||
accum = accum|(arr[3] & 0xff) << 24; |
||||
return Float.intBitsToFloat(accum); |
||||
} |
||||
} |
||||
Loading…
Reference in new issue