Compare commits
5 Commits
Author | SHA1 | Date | |
---|---|---|---|
e7a860ef16 | |||
1cbaa5795c | |||
15203f0edd | |||
ed180d6f18 | |||
c0c33f6c2e |
@ -0,0 +1,33 @@
|
||||
package com.fuyuanshen.modules.mqtt.config;
|
||||
|
||||
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.integration.mqtt.core.DefaultMqttPahoClientFactory;
|
||||
import org.springframework.integration.mqtt.core.MqttPahoClientFactory;
|
||||
|
||||
/**
|
||||
* @Author: HarryLin
|
||||
* @Date: 2025/3/20 14:40
|
||||
* @Company: 北京红山信息科技研究院有限公司
|
||||
* @Email: linyun@***.com.cn
|
||||
**/
|
||||
@Configuration
|
||||
public class MqttConfiguration {
|
||||
@Autowired
|
||||
private MqttPropertiesConfig mqttPropertiesConfig;
|
||||
/** 创建连接工厂 **/
|
||||
@Bean
|
||||
public MqttPahoClientFactory mqttPahoClientFactory(){
|
||||
DefaultMqttPahoClientFactory factory = new DefaultMqttPahoClientFactory();
|
||||
MqttConnectOptions options = new MqttConnectOptions();
|
||||
options.setCleanSession(true); //设置新会话
|
||||
options.setUserName(mqttPropertiesConfig.getUsername());
|
||||
options.setPassword(mqttPropertiesConfig.getPassword().toCharArray());
|
||||
options.setServerURIs(new String[]{mqttPropertiesConfig.getUrl()});
|
||||
factory.setConnectionOptions(options);
|
||||
return factory;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package com.fuyuanshen.modules.mqtt.config;
|
||||
|
||||
import org.springframework.integration.annotation.MessagingGateway;
|
||||
import org.springframework.integration.mqtt.support.MqttHeaders;
|
||||
import org.springframework.messaging.handler.annotation.Header;
|
||||
|
||||
/**
|
||||
* @Author: HarryLin
|
||||
* @Date: 2025/3/20 17:06
|
||||
* @Company: 北京红山信息科技研究院有限公司
|
||||
* @Email: linyun@***.com.cn
|
||||
**/
|
||||
@MessagingGateway(defaultRequestChannel = "mqttOutboundChannel")
|
||||
public interface MqttGateway {
|
||||
public abstract void sendMsgToMqtt(@Header(value = MqttHeaders.TOPIC) String topic, String payload);
|
||||
public abstract void sendMsgToMqtt(@Header(value = MqttHeaders.TOPIC) String topic, @Header(value = MqttHeaders.QOS) int qos, String payload );
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
package com.fuyuanshen.modules.mqtt.config;
|
||||
|
||||
|
||||
import com.fuyuanshen.modules.mqtt.receiver.ReceiverMessageHandler;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.integration.annotation.ServiceActivator;
|
||||
import org.springframework.integration.channel.DirectChannel;
|
||||
import org.springframework.integration.core.MessageProducer;
|
||||
import org.springframework.integration.mqtt.core.MqttPahoClientFactory;
|
||||
import org.springframework.integration.mqtt.inbound.MqttPahoMessageDrivenChannelAdapter;
|
||||
import org.springframework.integration.mqtt.support.DefaultPahoMessageConverter;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
import org.springframework.messaging.MessageHandler;
|
||||
|
||||
/**
|
||||
* @Author: HarryLin
|
||||
* @Date: 2025/3/20 14:54
|
||||
* @Company: 北京红山信息科技研究院有限公司
|
||||
* @Email: linyun@***.com.cn
|
||||
**/
|
||||
@Configuration
|
||||
public class MqttInboundConfiguration {
|
||||
@Autowired
|
||||
private MqttPropertiesConfig mqttPropertiesConfig;
|
||||
@Autowired
|
||||
private MqttPahoClientFactory mqttPahoClientFactory;
|
||||
@Autowired
|
||||
private ReceiverMessageHandler receiverMessageHandler;
|
||||
//消息通道
|
||||
@Bean
|
||||
public MessageChannel messageInboundChannel(){
|
||||
return new DirectChannel();
|
||||
}
|
||||
|
||||
/**
|
||||
* 配置入站适配器
|
||||
* 作用: 设置订阅主题,以及指定消息的通道 等相关属性
|
||||
* */
|
||||
@Bean
|
||||
public MessageProducer messageProducer(){
|
||||
MqttPahoMessageDrivenChannelAdapter mqttPahoMessageDrivenChannelAdapter = new MqttPahoMessageDrivenChannelAdapter(
|
||||
mqttPropertiesConfig.getUrl(),
|
||||
mqttPropertiesConfig.getSubClientId(),
|
||||
mqttPahoClientFactory,
|
||||
mqttPropertiesConfig.getSubTopic().split(",")
|
||||
);
|
||||
mqttPahoMessageDrivenChannelAdapter.setQos(1);
|
||||
mqttPahoMessageDrivenChannelAdapter.setConverter(new DefaultPahoMessageConverter());
|
||||
mqttPahoMessageDrivenChannelAdapter.setOutputChannel(messageInboundChannel());
|
||||
return mqttPahoMessageDrivenChannelAdapter;
|
||||
}
|
||||
/** 指定处理消息来自哪个通道 */
|
||||
@Bean
|
||||
@ServiceActivator(inputChannel = "messageInboundChannel")
|
||||
public MessageHandler messageHandler(){
|
||||
return receiverMessageHandler;
|
||||
}
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
package com.fuyuanshen.modules.mqtt.config;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.integration.annotation.ServiceActivator;
|
||||
import org.springframework.integration.channel.DirectChannel;
|
||||
import org.springframework.integration.mqtt.core.MqttPahoClientFactory;
|
||||
import org.springframework.integration.mqtt.outbound.MqttPahoMessageHandler;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
import org.springframework.messaging.MessageHandler;
|
||||
|
||||
/**
|
||||
* @Author: HarryLin
|
||||
* @Date: 2025/3/20 15:46
|
||||
* @Company: 北京红山信息科技研究院有限公司
|
||||
* @Email: linyun@***.com.cn
|
||||
**/
|
||||
@Configuration
|
||||
@Slf4j
|
||||
public class MqttOutboundConfiguration {
|
||||
@Autowired
|
||||
private MqttPropertiesConfig mqttPropertiesConfig;
|
||||
@Autowired
|
||||
private MqttPahoClientFactory mqttPahoClientFactory;
|
||||
|
||||
// 消息通道
|
||||
@Bean
|
||||
public MessageChannel mqttOutboundChannel(){
|
||||
return new DirectChannel();
|
||||
}
|
||||
|
||||
|
||||
/** 配置出站消息处理器 */
|
||||
@Bean
|
||||
@ServiceActivator(inputChannel = "mqttOutboundChannel") // 指定处理器针对哪个通道的消息进行处理
|
||||
public MessageHandler mqttOutboundMessageHandler(){
|
||||
MqttPahoMessageHandler mqttPahoMessageHandler = new MqttPahoMessageHandler(
|
||||
mqttPropertiesConfig.getUrl(),
|
||||
mqttPropertiesConfig.getPubClientId(),
|
||||
mqttPahoClientFactory
|
||||
);
|
||||
mqttPahoMessageHandler.setDefaultQos(1);
|
||||
mqttPahoMessageHandler.setDefaultTopic("worker/location");
|
||||
mqttPahoMessageHandler.setAsync(true);
|
||||
return mqttPahoMessageHandler;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package com.fuyuanshen.modules.mqtt.config;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* @Author: HarryLin
|
||||
* @Date: 2025/3/20 14:32
|
||||
* @Company: 北京红山信息科技研究院有限公司
|
||||
* @Email: linyun@***.com.cn
|
||||
**/
|
||||
@Data
|
||||
@ConfigurationProperties(prefix = "mqtt")
|
||||
@Component
|
||||
public class MqttPropertiesConfig {
|
||||
private String username;
|
||||
private String password;
|
||||
private String url;
|
||||
private String subClientId;
|
||||
private String subTopic;
|
||||
private String pubClientId;
|
||||
private String pubTopic;
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package com.fuyuanshen.modules.mqtt.publish;
|
||||
|
||||
import com.fuyuanshen.annotation.rest.AnonymousGetMapping;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/device")
|
||||
@Slf4j
|
||||
public class DeviceDataController {
|
||||
|
||||
@Autowired
|
||||
private MqttClientTest mqttClientTest;
|
||||
|
||||
// @PostMapping("/{deviceId}/command")
|
||||
@AnonymousGetMapping(value = "/test/command")
|
||||
public ResponseEntity<String> sendCommand() {
|
||||
|
||||
mqttClientTest.sendMsg();
|
||||
return ResponseEntity.ok("success");
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
package com.fuyuanshen.modules.mqtt.publish;
|
||||
|
||||
|
||||
import com.fuyuanshen.modules.mqtt.config.MqttGateway;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class MqttClientTest {
|
||||
@Autowired
|
||||
private MqttGateway mqttGateway;
|
||||
|
||||
public void sendMsg() {
|
||||
mqttGateway.sendMsgToMqtt("worker/location/1", "hello mqtt spring boot");
|
||||
log.info("message is send");
|
||||
|
||||
mqttGateway.sendMsgToMqtt("worker/alert/2", "hello mqtt spring boot2");
|
||||
log.info("message is send2");
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package com.fuyuanshen.modules.mqtt.publish;
|
||||
|
||||
import com.fuyuanshen.modules.mqtt.config.MqttGateway;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.integration.mqtt.support.MqttHeaders;
|
||||
import org.springframework.messaging.handler.annotation.Header;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* @Author: HarryLin
|
||||
* @Date: 2025/3/20 16:16
|
||||
* @Company: 北京红山信息科技研究院有限公司
|
||||
* @Email: linyun@***.com.cn
|
||||
**/
|
||||
@Service
|
||||
public class MqttMessageSender {
|
||||
@Autowired
|
||||
private MqttGateway mqttGateway;
|
||||
public void sendMsg(@Header(value = MqttHeaders.TOPIC) String topic, String payload) {
|
||||
mqttGateway.sendMsgToMqtt(topic,payload);
|
||||
}
|
||||
public void sendMsg(@Header(value = MqttHeaders.TOPIC) String topic, @Header(value = MqttHeaders.QOS) int qos, String payload) {
|
||||
mqttGateway.sendMsgToMqtt(topic,qos,payload);
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
package com.fuyuanshen.modules.mqtt.receiver;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessageHandler;
|
||||
import org.springframework.messaging.MessageHeaders;
|
||||
import org.springframework.messaging.MessagingException;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @Author: HarryLin
|
||||
* @Date: 2025/3/20 15:24
|
||||
* @Company: 北京红山信息科技研究院有限公司
|
||||
* @Email: linyun@***.com.cn
|
||||
**/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class ReceiverMessageHandler implements MessageHandler {
|
||||
@Override
|
||||
public void handleMessage(Message<?> message) throws MessagingException{
|
||||
Object payload = message.getPayload();
|
||||
MessageHeaders headers = message.getHeaders();
|
||||
String receivedTopic = Objects.requireNonNull(headers.get("mqtt_receivedTopic")).toString();
|
||||
String receivedQos = Objects.requireNonNull(headers.get("mqtt_receivedQos")).toString();
|
||||
String timestamp = Objects.requireNonNull(headers.get("timestamp")).toString();
|
||||
log.info("MQTT payload= {} \n receivedTopic = {} \n receivedQos = {} \n timestamp = {}"
|
||||
,payload,receivedTopic,receivedQos,timestamp);
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package com.fuyuanshen.modules.security.config;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.integration.annotation.ServiceActivator;
|
||||
import org.springframework.integration.mqtt.support.MqttHeaders;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
public class DeviceDataService {
|
||||
|
||||
|
||||
@ServiceActivator(inputChannel = "mqttInputChannel")
|
||||
public void handleDeviceData(Message<?> message) {
|
||||
String topic = message.getHeaders().get(MqttHeaders.RECEIVED_TOPIC).toString();
|
||||
String payload = message.getPayload().toString();
|
||||
|
||||
// 解析设备数据
|
||||
if (topic.startsWith("device/data/")) {
|
||||
log.info("Received device data device/data/: {} {}", topic, payload);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -108,6 +108,9 @@ public class Device extends BaseEntity implements Serializable {
|
||||
@ApiModelProperty(value = "绑定状态")
|
||||
private Integer bindingStatus;
|
||||
|
||||
@ApiModelProperty(value = "通讯方式", example = "0:4G;1:蓝牙")
|
||||
private Integer communicationMode;
|
||||
|
||||
|
||||
public void copy(Device source) {
|
||||
BeanUtil.copyProperties(source, this, CopyOptions.create().setIgnoreNullValue(true));
|
||||
|
@ -9,6 +9,7 @@ import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fuyuanshen.base.BaseEntity;
|
||||
import com.fuyuanshen.modules.system.domain.Device;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
@ -100,6 +101,8 @@ public class APPDevice extends BaseEntity implements Serializable {
|
||||
@ApiModelProperty(value = "绑定类型")
|
||||
private Integer bindingType;
|
||||
|
||||
@Schema(name = "通讯方式", example = "0:4G;1:蓝牙")
|
||||
private String communicationMode;
|
||||
|
||||
public void copy(Device source) {
|
||||
BeanUtil.copyProperties(source, this, CopyOptions.create().setIgnoreNullValue(true));
|
||||
|
@ -13,10 +13,13 @@ import javax.validation.constraints.NotNull;
|
||||
@Data
|
||||
public class APPUnbindDTO {
|
||||
|
||||
@NotBlank(message = "设备MAC不能为空")
|
||||
// @NotBlank(message = "设备MAC不能为空")
|
||||
@ApiModelProperty(value = "设备MAC", required = true)
|
||||
private String deviceMac;
|
||||
|
||||
@ApiModelProperty(value = "设备IMEI")
|
||||
private String deviceImei;
|
||||
|
||||
@NotNull(message = "客户号不能为空")
|
||||
@ApiModelProperty(value = "客户号")
|
||||
private Long customerId;
|
||||
|
@ -22,6 +22,7 @@ import com.fuyuanshen.modules.system.mapper.app.APPDeviceMapper;
|
||||
import com.fuyuanshen.modules.system.mapper.app.AppDeviceTypeMapper;
|
||||
import com.fuyuanshen.utils.PageResult;
|
||||
import com.fuyuanshen.utils.SecurityUtils;
|
||||
import com.fuyuanshen.utils.StringUtils;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
@ -29,7 +30,6 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@ -86,6 +86,7 @@ public class APPDeviceServiceImpl extends ServiceImpl<APPDeviceMapper, APPDevice
|
||||
|
||||
List<Device> devices = new ArrayList<>();
|
||||
|
||||
|
||||
if (criteria.getCommunicationMode().equals(CommunicationModeEnum.BLUETOOTH.getValue())) {
|
||||
devices = deviceMapper.selectList(new QueryWrapper<Device>().eq("device_mac", criteria.getDeviceMac()));
|
||||
if (CollectionUtil.isEmpty(devices)) {
|
||||
@ -109,8 +110,9 @@ public class APPDeviceServiceImpl extends ServiceImpl<APPDeviceMapper, APPDevice
|
||||
throw new BadRequestException("该设备已绑定!!!");
|
||||
}
|
||||
}
|
||||
|
||||
Device device = devices.get(0);
|
||||
device.setCommunicationMode(criteria.getCommunicationMode());
|
||||
|
||||
device.setBindingStatus(BindingStatusEnum.BOUND.getCode());
|
||||
deviceMapper.updateById(device);
|
||||
|
||||
@ -159,18 +161,34 @@ public class APPDeviceServiceImpl extends ServiceImpl<APPDeviceMapper, APPDevice
|
||||
@Override
|
||||
@Transactional
|
||||
public void unbindAPPDevice(APPUnbindDTO deviceForm) {
|
||||
QueryWrapper<APPDevice> queryWrapper = new QueryWrapper<>();
|
||||
QueryWrapper<Device> qw = new QueryWrapper<>();
|
||||
if (StringUtils.isNotEmpty(deviceForm.getDeviceMac())) {
|
||||
queryWrapper.eq("device_mac", deviceForm.getDeviceMac());
|
||||
qw.eq("device_mac", deviceForm.getDeviceMac());
|
||||
}
|
||||
if (StringUtils.isNotEmpty(deviceForm.getDeviceImei())) {
|
||||
queryWrapper.eq("device_imei", deviceForm.getDeviceImei());
|
||||
qw.eq("device_imei", deviceForm.getDeviceImei());
|
||||
}
|
||||
queryWrapper.eq("binding_type", UserType.APP.getValue());
|
||||
APPDevice appDevice = appDeviceMapper.selectOne(queryWrapper);
|
||||
if (appDevice == null) {
|
||||
throw new BadRequestException("设备不存在!!!");
|
||||
}
|
||||
appDeviceMapper.delete(queryWrapper);
|
||||
|
||||
appDeviceMapper.delete(new QueryWrapper<APPDevice>().eq("device_mac", deviceForm.getDeviceMac()).eq("binding_type", UserType.APP.getValue()));
|
||||
List<Device> devices = deviceMapper.selectList(new QueryWrapper<Device>().eq("device_mac", deviceForm.getDeviceMac()));
|
||||
List<Device> devices = deviceMapper.selectList(qw);
|
||||
List<Long> ids = devices.stream()
|
||||
.map(Device::getId)
|
||||
.collect(Collectors.toList());
|
||||
if (CollectionUtil.isNotEmpty(ids)) {
|
||||
appDeviceTypeMapper.deleteBatchIds(ids);
|
||||
}
|
||||
Device device = new Device();
|
||||
device.setId(deviceForm.getCustomerId());
|
||||
device.setId(appDevice.getId());
|
||||
device.setBindingStatus(BindingStatusEnum.UNBOUND.getCode());
|
||||
deviceMapper.updateById(device);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -651,7 +651,15 @@ public class DeviceServiceImpl extends ServiceImpl<DeviceMapper, Device> impleme
|
||||
@Override
|
||||
@Transactional
|
||||
public void unbindDevice(DeviceForm deviceForm) {
|
||||
appDeviceMapper.delete(new QueryWrapper<APPDevice>().eq("device_mac", deviceForm.getDeviceMac()));
|
||||
|
||||
QueryWrapper<APPDevice> queryWrapper = new QueryWrapper<>();
|
||||
if (StringUtils.isNotEmpty(deviceForm.getDeviceMac())) {
|
||||
queryWrapper.eq("device_mac", deviceForm.getDeviceMac());
|
||||
}
|
||||
if (StringUtils.isNotEmpty(deviceForm.getDeviceImei())) {
|
||||
queryWrapper.eq("device_imei", deviceForm.getDeviceImei());
|
||||
}
|
||||
appDeviceMapper.delete(queryWrapper);
|
||||
Device device = new Device();
|
||||
device.setId(deviceForm.getId());
|
||||
device.setBindingStatus(BindingStatusEnum.UNBOUND.getCode());
|
||||
|
@ -4,9 +4,9 @@ spring:
|
||||
druid:
|
||||
db-type: com.alibaba.druid.pool.DruidDataSource
|
||||
driverClassName: com.p6spy.engine.spy.P6SpyDriver
|
||||
url: jdbc:p6spy:mysql://192.168.2.23:3306/eladmin?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false
|
||||
url: jdbc:p6spy:mysql://120.79.224.186:3366/eladmin?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false
|
||||
username: root
|
||||
password: root
|
||||
password: 1fys@QWER..
|
||||
# 初始连接数,建议设置为与最小空闲连接数相同
|
||||
initial-size: 20
|
||||
# 最小空闲连接数,保持足够的空闲连接以应对请求
|
||||
@ -53,10 +53,10 @@ spring:
|
||||
|
||||
redis:
|
||||
#数据库索引
|
||||
database: ${REDIS_DB:2}
|
||||
host: ${REDIS_HOST:123.207.99.140}
|
||||
port: ${REDIS_PORT:6379}
|
||||
password: ${REDIS_PWD:ccxx11234}
|
||||
database: ${REDIS_DB:0}
|
||||
host: ${REDIS_HOST:120.79.224.186}
|
||||
port: ${REDIS_PORT:26379}
|
||||
password: ${REDIS_PWD:1fys@QWER..}
|
||||
#连接超时时间
|
||||
timeout: 5000
|
||||
# 连接池配置
|
||||
@ -149,3 +149,13 @@ file:
|
||||
logging:
|
||||
level:
|
||||
com.fuyuanshen: debug
|
||||
|
||||
# MQTT配置
|
||||
mqtt:
|
||||
username: admin
|
||||
password: fys123456
|
||||
url: tcp://47.107.152.87:1883
|
||||
subClientId: wuLang_subClient_01
|
||||
subTopic: worker/alert/#,worker/location/#
|
||||
pubTopic: worker/location
|
||||
pubClientId: wuLang_pubClient_01
|
@ -155,3 +155,14 @@ file:
|
||||
pic: /home/eladmin/app_avatar/ #设备图片存储路径
|
||||
#ip: http://fuyuanshen.com:81/ #服务器地址
|
||||
ip: https://fuyuanshen.com/ #服务器地址
|
||||
|
||||
|
||||
# MQTT配置
|
||||
mqtt:
|
||||
username: admin
|
||||
password: fys123456
|
||||
url: tcp://47.107.152.87:1883
|
||||
subClientId: wuLang_subClient_01
|
||||
subTopic: worker/alert/#,worker/location/#
|
||||
pubTopic: worker/location
|
||||
pubClientId: wuLang_pubClient_01
|
@ -34,7 +34,7 @@ spring:
|
||||
check-template-location: false
|
||||
profiles:
|
||||
# 激活的环境,如果需要 quartz 分布式支持,需要修改 active: dev,quartz
|
||||
active: dev
|
||||
active: prod
|
||||
data:
|
||||
redis:
|
||||
repositories:
|
||||
|
@ -21,7 +21,7 @@
|
||||
|
||||
<!-- APP用户设备列表 -->
|
||||
<select id="appDeviceList" resultType="com.fuyuanshen.modules.system.domain.app.APPDevice">
|
||||
select d.* from app_device as d
|
||||
select d.* ,d.app_device_id AS id from app_device as d
|
||||
<where>
|
||||
<!-- 时间范围等其他条件保持原样 -->
|
||||
<if test="criteria.deviceName != null and criteria.deviceName.trim() != ''">
|
||||
@ -87,5 +87,4 @@
|
||||
order by d.create_time desc
|
||||
</select>
|
||||
|
||||
|
||||
</mapper>
|
@ -0,0 +1,90 @@
|
||||
package com.fuyuanshen.utils;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class ImageToCArrayConverter {
|
||||
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
convertImageToCArray("C:\\work\\6170_强光_160_80_2.jpg", "output.c", 160, 80);
|
||||
System.out.println("转换成功!");
|
||||
} catch (IOException e) {
|
||||
System.err.println("转换失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public static void convertImageToCArray(String inputPath, String outputPath,
|
||||
int width, int height) throws IOException {
|
||||
// 读取原始图片
|
||||
BufferedImage originalImage = ImageIO.read(new File(inputPath));
|
||||
|
||||
// 调整图片尺寸
|
||||
BufferedImage resizedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
|
||||
resizedImage.getGraphics().drawImage(
|
||||
originalImage, 0, 0, width, height, null);
|
||||
|
||||
// 转换像素数据为RGB565格式(高位在前)
|
||||
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
int rgb = resizedImage.getRGB(x, y);
|
||||
|
||||
// 提取RGB分量
|
||||
int r = (rgb >> 16) & 0xFF;
|
||||
int g = (rgb >> 8) & 0xFF;
|
||||
int b = rgb & 0xFF;
|
||||
|
||||
// 转换为RGB565(5位红,6位绿,5位蓝)
|
||||
int r5 = (r >> 3) & 0x1F;
|
||||
int g6 = (g >> 2) & 0x3F;
|
||||
int b5 = (b >> 3) & 0x1F;
|
||||
|
||||
// 组合为16位值
|
||||
int rgb565 = (r5 << 11) | (g6 << 5) | b5;
|
||||
|
||||
// 高位在前(大端序)写入字节
|
||||
byteStream.write((rgb565 >> 8) & 0xFF); // 高字节
|
||||
byteStream.write(rgb565 & 0xFF); // 低字节
|
||||
}
|
||||
}
|
||||
|
||||
byte[] imageData = byteStream.toByteArray();
|
||||
|
||||
// 生成C语言数组文件
|
||||
try (FileOutputStream fos = new FileOutputStream(outputPath)) {
|
||||
// 写入注释行(包含尺寸信息)
|
||||
String header = String.format("/* 0X10,0X10,0X00,0X%02X,0X00,0X%02X,0X01,0X1B, */\n",
|
||||
width, height);
|
||||
fos.write(header.getBytes());
|
||||
|
||||
// 写入数组声明
|
||||
fos.write("const unsigned char gImage_data[] = {\n".getBytes());
|
||||
|
||||
// 写入数据(每行16个字节)
|
||||
for (int i = 0; i < imageData.length; i++) {
|
||||
// 写入0X前缀
|
||||
fos.write(("0X" + String.format("%02X", imageData[i] & 0xFF)).getBytes());
|
||||
|
||||
// 添加逗号(最后一个除外)
|
||||
if (i < imageData.length - 1) {
|
||||
fos.write(',');
|
||||
}
|
||||
|
||||
// 换行和缩进
|
||||
if ((i + 1) % 16 == 0) {
|
||||
fos.write('\n');
|
||||
} else {
|
||||
fos.write(' ');
|
||||
}
|
||||
}
|
||||
|
||||
// 写入数组结尾
|
||||
fos.write("\n};\n".getBytes());
|
||||
}
|
||||
}
|
||||
}
|
8
pom.xml
8
pom.xml
@ -223,6 +223,14 @@
|
||||
<artifactId>commons-text</artifactId>
|
||||
<version>1.13.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-integration</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.integration</groupId>
|
||||
<artifactId>spring-integration-mqtt</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
Reference in New Issue
Block a user