springboot 物联网_【阿里云生活物联网架构师专题】基于在 SpringBoot Java私有云上对接阿里云物联网,实现M2M设备数据流转。...

本文介绍了如何在SpringBoot应用中利用阿里云物联网平台实现服务器订阅,适用于高并发设备数据接收场景。通过详细步骤演示创建订阅及配置,并分享了相关开源项目链接,帮助开发者实践M2M设备数据流转。
摘要由CSDN通过智能技术生成
3ea4bfbf197f21278128f73aeb5f9005.png

近处是人生,远处是风景 -

今天与老同学小聚一餐,君子之交淡如水,忆当年青春岁月。年龄越大,志同道合的朋友越来越少了,一声朋友,足以抵过无限岁月!

在儿时,总喜欢做一些天马行空的美梦,想象着可以仗剑直走天涯,也想象着可以遨游全世界,看遍这世界的每一处风景。

可是,长大之后才会发现,所有的梦想都要立足于当下的实际。有些梦想,通过努力可以达成现实,而有些梦想,永远都只会是幻想。

活着,不要一味地向往着远方,也不要一味地想要追求那些遥远的东西。

要知道,远处的风景固然美好,脑海中的梦想也固然恢弘。但每一个美好的未来,都是需脚踏实地坚持做下去,才有资格享受那份用汗水换来的成果! 不要坐享其成,因为我们都是受过高等教育的人,要不然读书为了什么?

读书这么多年,不是为了雄辩和驳斥,也不是为了轻信和盲从,而是为了思考和权衡自己的人生何去何从!

愿你在孤独难熬的时光,始终不会辜负拼命的自己;

5e8f861e36ad5d06aad504dc196a51d9.png

半颗心脏

1 前言 针对不少电商类型公司想玩转物联网开发的问题,我们的私有云服务器如何接收来自阿里云物联网的设备的状态和数据呢? 今天周末,我给大家啊,介绍下如何在 Java 语言开发( 基于SpringBoot 框架 )的私有云上实现!本来这些技术都是开源免费的,动下手笔给大家带来一些启发!

什么是服务器订阅?

私有云可以直接订阅产品下多种类型的消息:设备上报消息、设备状态变化通知、设备生命周期变更、网关发现子设备上报、设备拓扑关系变更等。配置服务端订阅后,物联网平台会将产品下所有设备的已订阅类型的消息转发至您的服务器。

适用场景

1、服务端订阅适用于单纯的接收设备数据的场景,并且适用于高并发场景。

2、服务端接收产品下全部设备的订阅数据。

3、如果您有多个服务器消费同一个产品的订阅消息,消息会随机转发至某个服务器。

4、服务端订阅与规则引擎数据流转的使用场景和能力对比,请参见数据流转方案对比。

今天使用的是 SpringBoot 架构语言,这个也是我擅长开发的架构,所以这篇我给大家介绍下如何集成AMQP高级消息队列协议,配置AMQP服务端订阅后,物联网平台会将产品下所有已订阅类型的消息,通过AMQP通道推送至私有云。 7341ee53fd8263433db8af00ed1f4f9b.png 2 配置AMQP服务器订阅 在物联网平台控制台设置服务端订阅的消息类型。 1.登录 物联网平台控制台 。 2.在实例概览页,找到对应的实例,单击实例进入实例详情页;

882d5fe31512943dc2cedffb14b79e71.png

3.在左侧导航栏,选择规则引擎 > 服务端订阅。

4.在服务端订阅页,单击创建订阅。

5.在创建订阅对话框中,完成配置,单击确认。

607f7a4940451c5cffe237ef3be88ca2.png 3 开始集成 maven集成架包:
        
        com.aliyunaliyun-java-sdk-core4.5.6
        
        
        com.aliyunaliyun-java-sdk-iot7.16.0
        
        com.aliyun.openservicesiot-client-message1.1.5
        
        org.apache.qpidqpid-jms-client0.47.0
        
        commons-codeccommons-codec1.10

整个接收处理类如下,其中,要注意的是以下几个参数,其实在阿里云官网描述得非常清楚了点我:

参数说明
accessKey阿里云账号的AccessKey Key
accessSecret阿里云账号的AccessKey Secret
consumerGroupId消费组ID。登录物联网平台控制台,在对应实例的规则引擎 > 服务端订阅 > 消费组列表查看您的消费组ID。
iotInstanceId实例ID。仅您购买的实例需要传入;如果是公共示例,留空即可。
connectionUrl见下面的详细描述
AMQP客户端接入物联网平台的连接地址和连接认证参数说明如下: 对于您购买的实例,接入域名请在物联网平台控制台,找到对应的实例,单击实例进入实例详情查看。 公共实例的接入域名,其域名中的变量说明:

${uid}.iot-amqp.${regionId}.aliyuncs.com

字段说明
uid您的阿里云账号ID。可登录物联网平台控制台,单击头像,跳转至安全设置页面查看
regionId您的物联网平台服务所在地域ID。在物联网平台控制台左上方可查看地域。RegionId的表达方法,请参见地域和可用区。
@SpringBootApplication
public class DemoApplication {

    private final static Logger logger = LoggerFactory.getLogger(DemoApplication.class);

    //业务处理异步线程池,线程池参数可以根据您的业务特点调整,或者您也可以用其他异步方式处理接收到的消息。
    private final static ExecutorService executorService = new ThreadPoolExecutor(
            Runtime.getRuntime().availableProcessors(),
            Runtime.getRuntime().availableProcessors() * 2, 60, TimeUnit.SECONDS,
            new LinkedBlockingQueue<>(50000));

    public static void main(String[] args) {

        SpringApplication.run(DemoApplication.class, args);

        //参数说明,请参见AMQP客户端接入说明文档。
        String accessKey = "LTAI4Fg3**********GYJBLPoTo5";
        String accessSecret = "OT7s9vk*********K4p8KQ31qoTIL4";
        String consumerGroupId = "DEFAULT_GROUP";
        //iotInstanceId:购买的实例请填写实例ID,公共实例请填空字符串""。
        String iotInstanceId = "";
        long timeStamp = System.currentTimeMillis();
        //签名方法:支持hmacmd5、hmacsha1和hmacsha256。
        String signMethod = "hmacsha1";
        //控制台服务端订阅中消费组状态页客户端ID一栏将显示clientId参数。
        //建议使用机器UUID、MAC地址、IP等唯一标识等作为clientId。便于您区分识别不同的客户端。
        String clientId = "xuhongv";

        //userName组装方法,请参见AMQP客户端接入说明文档。
        String userName = clientId + "|authMode=aksign"
                + ",signMethod=" + signMethod
                + ",timestamp=" + timeStamp
                + ",authId=" + accessKey
                + ",iotInstanceId=" + iotInstanceId
                + ",consumerGroupId=" + consumerGroupId
                + "|";
        //计算签名,password组装方法,请参见AMQP客户端接入说明文档。
        String signContent = "authId=" + accessKey + "&timestamp=" + timeStamp;

        String password = null;
        try {
            password = doSign(signContent, accessSecret, signMethod);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //接入域名,请参见AMQP客户端接入说明文档。
        String connectionUrl = "failover:(amqps://13933000001932702.iot-amqp.cn-shanghai.aliyuncs.com:5671?amqp.idleTimeout=80000)"
                + "?failover.reconnectDelay=15";
        Hashtable hashtable = new Hashtable<>();
        hashtable.put("connectionfactory.SBCF", connectionUrl);
        hashtable.put("queue.QUEUE", "default");
        hashtable.put(Context.INITIAL_CONTEXT_FACTORY, "org.apache.qpid.jms.jndi.JmsInitialContextFactory");
        Context context = null;try {
            context = new InitialContext(hashtable);
        } catch (NamingException e) {
            e.printStackTrace();
        }
        ConnectionFactory cf = null;
        Destination queue = null;try {
            cf = (ConnectionFactory) context.lookup("SBCF");
            queue = (Destination) context.lookup("QUEUE");
        } catch (NamingException e) {
            e.printStackTrace();
        }// Create Connection
        Connection connection = null;try {
            connection = cf.createConnection(userName, password);
        } catch (JMSException e) {
            e.printStackTrace();
        }
        ((JmsConnection) connection).addConnectionListener(myJmsConnectionListener);// Create Session// Session.CLIENT_ACKNOWLEDGE: 收到消息后,需要手动调用message.acknowledge()// Session.AUTO_ACKNOWLEDGE: SDK自动ACK(推荐)
        Session session = null;try {
            session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
            connection.start();
        } catch (JMSException e) {
            e.printStackTrace();
        }try {// Create Receiver Link
            MessageConsumer consumer = session.createConsumer(queue);
            consumer.setMessageListener(messageListener);
        } catch (JMSException e) {
            e.printStackTrace();
        }
    }private static MessageListener messageListener = new MessageListener() {@Overridepublic void onMessage(Message message) {try {//1.收到消息之后一定要ACK。// 推荐做法:创建Session选择Session.AUTO_ACKNOWLEDGE,这里会自动ACK。// 其他做法:创建Session选择Session.CLIENT_ACKNOWLEDGE,这里一定要调message.acknowledge()来ACK。// message.acknowledge();//2.建议异步处理收到的消息,确保onMessage函数里没有耗时逻辑。// 如果业务处理耗时过程过长阻塞住线程,可能会影响SDK收到消息后的正常回调。
                executorService.submit(() -> processMessage(message));
            } catch (Exception e) {
                logger.error("submit task occurs exception ", e);
            }
        }
    };/**
     * 在这里处理您收到消息后的具体业务逻辑。
     */private static void processMessage(Message message) {try {byte[] body = message.getBody(byte[].class);
            String content = new String(body);
            String topic = message.getStringProperty("topic");
            String messageId = message.getStringProperty("messageId");
            logger.info("receive message"
                    + ", topic = " + topic
                    + ", messageId = " + messageId
                    + ", content = " + content);
        } catch (Exception e) {
            logger.error("processMessage occurs error ", e);
        }
    }private static JmsConnectionListener myJmsConnectionListener = new JmsConnectionListener() {/**
         * 连接成功建立。
         */@Overridepublic void onConnectionEstablished(URI remoteURI) {
            logger.info("onConnectionEstablished, remoteUri:{}", remoteURI);
        }/**
         * 尝试过最大重试次数之后,最终连接失败。
         */@Overridepublic void onConnectionFailure(Throwable error) {
            logger.error("onConnectionFailure, {}", error.getMessage());
        }/**
         * 连接中断。
         */@Overridepublic void onConnectionInterrupted(URI remoteURI) {
            logger.info("onConnectionInterrupted, remoteUri:{}", remoteURI);
        }/**
         * 连接中断后又自动重连上。
         */@Overridepublic void onConnectionRestored(URI remoteURI) {
            logger.info("onConnectionRestored, remoteUri:{}", remoteURI);
        }@Overridepublic void onInboundMessage(JmsInboundMessageDispatch envelope) {
        }@Overridepublic void onSessionClosed(Session session, Throwable cause) {
        }@Overridepublic void onConsumerClosed(MessageConsumer consumer, Throwable cause) {
        }@Overridepublic void onProducerClosed(MessageProducer producer, Throwable cause) {
        }
    };/**
     * 计算签名,password组装方法,请参见AMQP客户端接入说明文档。
     */private static String doSign(String toSignString, String secret, String signMethod) throws Exception {
        SecretKeySpec signingKey = new SecretKeySpec(secret.getBytes(), signMethod);
        Mac mac = Mac.getInstance(signMethod);
        mac.init(signingKey);byte[] rawHmac = mac.doFinal(toSignString.getBytes());return Base64.encodeBase64String(rawHmac);
    }
}
当设备正常推送数据上报,服务器会接收到: 39fdca955988696e6e298ce1a4c0a4fc.png
2020-11-20 15:43:04.266  INFO 2108 --- [pool-1-thread-1] com.example.demo.DemoApplication         : receive message, topic = /a1quyJFAxPS/Device01/thing/event/property/post, messageId = 1329691716009393153, content = 

{
 "deviceType": "WaterloggingSensor",
 "iotId": "PZzjOxtNUvQ2jlpATdPs000000",
 "requestId": "123",
 "checkFailedData": {},
 "productKey": "a1quoiyJF0",
 "gmtCreate": 1605858184226,
 "deviceName": "Device01",
 "items": {
  "BatteryLevel": {
   "value": 1,
   "time": 1605858184231
  },
  "WaterLeachState": {
   "value": 1,
   "time": 1605858184231
  },
  "GeoLocation": {
   "value": {
    "CoordinateSystem": 1,
    "Latitude": 11,
    "Longitude": 11,
    "Altitude": 1
   },
   "time": 1605858184231
  }
 }
}

推荐

 · 我的其他开源项目 ·  

87136cf7f8c4f1a107a09e6e3e5a1947.gif

1、小程序连接mqtt服务器,控制esp8266:

https://github.com/xuhongv/WeChatMiniEsp8266

2、公众号airkiss配网、近场发现在esp8266:

https://github.com/xuhongv/xLibEsp8266Rtos3.1AirKiss

3、公众号airkiss配网、近场发现在esp32:

https://github.com/xuhongv/xLibEsp32IdfAirKiss

4、小程序控制esp8266实现七彩效果项目源码:

https://github.com/xuhongv/WCMiniColorSetForEsp8266

5、微信小程序蓝牙配网blufi实现在esp32源码:

https://github.com/xuhongv/BlufiEsp32WeChat

6、微信小程序蓝牙ble控制esp32七彩灯效果:

https://blog.csdn.net/xh870189248/article/details/101849759

7、可商用的事件分发的微信小程序mqtt框架:

https://blog.csdn.net/xh870189248/article/details/88718302

8、微信小程序mqtt连接阿里云IOT物联网平台

https://blog.csdn.net/xh870189248/article/details/91490697

9、微信公众号网页实现连接mqtt服务器

https://blog.csdn.net/xh870189248/article/details/100738444

355a8c5c283c21cfcf003b1995a2e764.png

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值