diff --git a/.idea/iotos-soft-gateway-demo.iml b/.idea/iotos-soft-gateway-demo.iml index 65eb2b6be21c2c2c53bac26eb23668082cb55d0f..e53dca1516b954a2c79bb3a98531fdb7e8967ff0 100644 --- a/.idea/iotos-soft-gateway-demo.iml +++ b/.idea/iotos-soft-gateway-demo.iml @@ -12,6 +12,9 @@ + + + diff --git a/README.md b/README.md index d2e1db01eb559191522a74808b8aa5bce06239b3..df91b9ee78439153e449685eb6bc0031349813a1 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,25 @@ 参考 [软网关开发说明](https://gitee.com/geekhekr/iotos-soft-gateway/blob/master/README.md#%E4%B8%9A%E5%8A%A1%E5%BC%80%E5%8F%91) +pom 需要依赖 + +```xml + + me.hekr.iotos.softgateway + framework-core + 0.0.1 + +``` + +tcp 和 udp 按需依赖。 + +如果 sdk 不能满足,可以 fork sdk 项目,提交 pr,或者自行 fork 之后按照项目发布说明发布到自己的仓库,然后依赖地址改为自己的 git 地址即可。 + ## 打包 开发完成后,将网关和子设备产品导出,(如果有其他文件也可以)放到 docs 文件夹下, 执行命令 `mvn clean package -Dmaven.test.skip=true` 会打包 jar 并将 README,docs 文件夹下的文件一并打包成 zip,生产的文件在 `target` 目录下。 + +## 项目示例说明 + +本项目模拟了一个简单广播系统,(因为需要广播系统的服务端,所以项目启动了一个udp server)。驱动(客户端)定时发送查询帧查询设备状态,然后上报给 IoT 平台。 \ No newline at end of file diff --git a/pom.xml b/pom.xml index 2b5719acfb69ef4d99ca243214017c0393e8df4c..af9b16f56cc4a056f299522ad4425964493ed7a8 100644 --- a/pom.xml +++ b/pom.xml @@ -30,6 +30,12 @@ framework-core 0.0.1 + + + me.hekr.iotos.softgateway + framework-network-udp + 0.0.1 + diff --git a/src/main/java/me/hekr/iotos/softgateway/subsystem/IoTGatewayApplication.java b/src/main/java/me/hekr/iotos/softgateway/subsystem/IoTGatewayApplication.java index 40d3be60b2014dbcdaf08bcc353c813fc4758994..e7b861c74e0c6fb6cf3291b49542e8ae05fcfb7b 100644 --- a/src/main/java/me/hekr/iotos/softgateway/subsystem/IoTGatewayApplication.java +++ b/src/main/java/me/hekr/iotos/softgateway/subsystem/IoTGatewayApplication.java @@ -10,7 +10,7 @@ import org.springframework.scheduling.annotation.EnableScheduling; @EnableScheduling public class IoTGatewayApplication { - public static void main(String[] args) throws Exception { + public static void main(String[] args) { SpringApplication.run(IoTGatewayApplication.class, args); } } diff --git a/src/main/java/me/hekr/iotos/softgateway/subsystem/config/SubsystemResourcesConfig.java b/src/main/java/me/hekr/iotos/softgateway/subsystem/config/SubsystemResourcesConfig.java new file mode 100644 index 0000000000000000000000000000000000000000..dd9e9cb417a1361506f70c91913cb62bc1adf9c8 --- /dev/null +++ b/src/main/java/me/hekr/iotos/softgateway/subsystem/config/SubsystemResourcesConfig.java @@ -0,0 +1,21 @@ +package me.hekr.iotos.softgateway.subsystem.config; + +import javax.annotation.PostConstruct; +import javax.annotation.PreDestroy; +import me.hekr.iotos.softgateway.subsystem.service.UdpServerService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** @author iotos */ +@Component +public class SubsystemResourcesConfig { + @Autowired private UdpServerService udpServerService; + + @PostConstruct + public void init() { + udpServerService.start(); + } + + @PreDestroy + public void close() {} +} diff --git a/src/main/java/me/hekr/iotos/softgateway/subsystem/dto/RadioDevice.java b/src/main/java/me/hekr/iotos/softgateway/subsystem/dto/RadioDevice.java new file mode 100644 index 0000000000000000000000000000000000000000..e26d5d1902881ab530e2a4809067146444299792 --- /dev/null +++ b/src/main/java/me/hekr/iotos/softgateway/subsystem/dto/RadioDevice.java @@ -0,0 +1,24 @@ +package me.hekr.iotos.softgateway.subsystem.dto; + +import lombok.Data; + +/** + * 广播设备 + * + * @author iotos + */ +@Data +public class RadioDevice { + + /** 设备id */ + private String radioDevId; + + /** 1 在线, 0离线 */ + private int status; + + /** 音量 */ + private int vol; + + /** 播放状态 0 停止, 1 播放, 2 暂停 */ + private int playStat; +} diff --git a/src/main/java/me/hekr/iotos/softgateway/subsystem/service/UdpServerService.java b/src/main/java/me/hekr/iotos/softgateway/subsystem/service/UdpServerService.java new file mode 100644 index 0000000000000000000000000000000000000000..9bb98c86637f0193dd6eb597658a0dda1e7beddf --- /dev/null +++ b/src/main/java/me/hekr/iotos/softgateway/subsystem/service/UdpServerService.java @@ -0,0 +1,134 @@ +package me.hekr.iotos.softgateway.subsystem.service; + +import static java.util.stream.Collectors.toList; + +import com.fasterxml.jackson.core.type.TypeReference; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.stream.IntStream; +import lombok.extern.slf4j.Slf4j; +import me.hekr.iotos.softgateway.core.config.DeviceMapper; +import me.hekr.iotos.softgateway.core.config.DeviceMapper.Props; +import me.hekr.iotos.softgateway.core.klink.KlinkService; +import me.hekr.iotos.softgateway.core.utils.JsonUtil; +import me.hekr.iotos.softgateway.network.common.DecodePacket; +import me.hekr.iotos.softgateway.network.common.PacketCoder; +import me.hekr.iotos.softgateway.network.udp.UdpClient; +import me.hekr.iotos.softgateway.network.udp.UdpServer; +import me.hekr.iotos.softgateway.subsystem.dto.RadioDevice; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Service; + +/** @author iotos */ +@Slf4j +@Service +public class UdpServerService { + private static final int SERVER_PORT = 1030; + private final PacketCoder packetCoder = getPacketCoder(); + private UdpServer udpServer; + private UdpClient udpClient; + @Autowired private KlinkService klinkService; + + private static PacketCoder getPacketCoder() { + return new PacketCoder() { + @Override + public byte[] encode(String s) { + return s.getBytes(StandardCharsets.UTF_8); + } + + @Override + public DecodePacket decode(byte[] bytes) { + return DecodePacket.wrap(new String(bytes, StandardCharsets.UTF_8), bytes.length); + } + }; + } + + @Scheduled(fixedDelay = 10 * 1000, initialDelay = 0) + public void syncDeviceStatus() { + List devices = + JsonUtil.fromJson( + udpClient.send("getAllStatus"), new TypeReference>() {}); + + for (RadioDevice d : devices) { + Optional subsystemDev = + DeviceMapper.getBySubSystemProperties(Props.p("radioDevId", d.getRadioDevId()).get()); + if (!subsystemDev.isPresent()) { + log.warn("没有配置映射设备信息,请在远程配置中进行配置,设备信息:{}", d); + continue; + } + + DeviceMapper dev = subsystemDev.get(); + + // 如果是离线,设置iot的设备离线 + if (d.getStatus() == 0) { + klinkService.devLogout(dev.getPk(), dev.getDevId()); + continue; + } + + Map params = new HashMap<>(3); + params.put("vol", d.getVol()); + params.put("playStat", d.getPlayStat()); + klinkService.devSend(dev.getPk(), dev.getDevId(), "report", params); + } + } + + public void start() { + startServer(); + startClient(); + } + + private void startClient() { + udpClient = new UdpClient<>("localhost", SERVER_PORT, 1021); + udpClient.setMessageListener( + ctx -> System.out.println("收到来自 " + ctx.getAddress() + " 的消息:" + ctx.getMessage())); + udpClient.setPacketCoder(packetCoder); + udpClient.setEnableNetLog(false); + udpClient.setSync(true); + // 同步模式设置超时时间 + udpClient.setTimeout(3000); + udpClient.start(); + } + + private void startServer() { + udpServer = new UdpServer<>(1030); + // 设置编解码 + udpServer.setPacketCoder(packetCoder); + + // 设置消息监听器 + udpServer.setMessageListener( + ctx -> { + // 模拟获取设备等信息 + String msg = ctx.getMessage(); + log.info("收到消息:{}", msg); + // 获取所有设备信息 + switch (msg) { + case "getAllStatus": + udpServer.send(ctx, JsonUtil.toJson(getDeviceStatus())); + break; + // 可以自行扩展其他指令 + default: + } + }); + // 开启网络日志 + udpServer.setEnableNetLog(true); + udpServer.start(); + } + + private List getDeviceStatus() { + return IntStream.range(0, 3) + .mapToObj( + i -> { + RadioDevice d = new RadioDevice(); + d.setRadioDevId("radio_id_" + i); + d.setStatus(i % 2); + d.setPlayStat(i % 3); + d.setVol(i); + return d; + }) + .collect(toList()); + } +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index ecf6bf0c7eceae9f48d37e5822659c9e145dbc7c..7df337413f4c4ee71adeb08c913ae87cbc831809 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -21,8 +21,9 @@ logging: # 比如 level.me.hekr.iotos: DEBUG level: root: INFO - me.hekr.iotos: INFO - io.netty: INFO + org.spring: WARN + me.hekr.iotos: DEBUG + io.netty: DEBUG # 日志文件保存位置 file: logs/iotos-soft-gateway.log