基于surging 的木舟平台如何通过HTTP网络组件接入设备
一、概述
上篇文章介绍了木舟如何上传模块热部署,那么此篇文章将介绍如何利用HTTP网络组件接入设备,那么有些人会问木舟又是什么,是什么架构为基础,能做什么呢?
木舟 (Kayak) 是什么?
木舟(Kayak)是基于.NET6.0软件环境下的surging微服务引擎进行开发的, 平台包含了微服务和物联网平台。支持异步和响应式编程开发,功能包含了物模型,设备,产品,网络组件的统一管理和微服务平台下的注册中心,服务路由,模块,中间服务等管理。还有多协议适配(TCP,MQTT,UDP,CoAP,HTTP,Grpc,websocket,rtmp,httpflv,webservice,等),通过灵活多样的配置适配能够接入不同厂家不同协议等设备。并且通过设备告警,消息通知,数据可视化等功能。能够让你能快速建立起微服务物联网平台系统。
那么下面就为大家介绍如何从创建组件、协议、设备网关,设备到设备网关接入,再到设备数据上报,把整个流程通过此篇文章进行阐述。
二、网络组件
1.编辑创建HTTP协议的网络组件,可以选择共享配置和独立配置(独立配置是集群模式),然后可以选择开启swagger和webservice.

开启成功后,可以看看swagger 是否可以访问

又或者是访问一下中间服务,以上篇文章上传的Testapi 模块为例:

三、自定义协议
- 如何创建自定义协议模块
如果是网络编程开发,必然会涉及到协议报文的编码解码处理,那么对于平台也是做到了灵活处理,首先是协议模块创建,通过以下代码看出协议模块可以添加协议说明md文档, 身份鉴权处理,HTTP路由,消息编解码,元数据配置。下面一一介绍如何进行编写
public class Demo5ProtocolSupportProvider : ProtocolSupportProvider
{
public override IObservable<ProtocolSupport> Create(ProtocolContext context)
{
var support = new ComplexProtocolSupport();
support.Id = "demo5";
support.Name = "演示协议5";
support.Description = "演示协议5";
support.AddDocument(MessageTransport.Http, "Document/document-http.md");
support.AddAuthenticator(MessageTransport.Http, new Demo5Authenticator());
support.AddRoutes(MessageTransport.Http, new List<BasicMessageCodec>() {
BasicMessageCodec.DeviceOnline,
BasicMessageCodec.ReportProperty,
BasicMessageCodec.WriteProperty,
BasicMessageCodec.ReadProperty,
BasicMessageCodec.Event
}.Select(p => HttpDescriptor.Instance(p.Pattern)
.GroupName(p.Route.GroupName())
.HttpMethod(p.Route.HttpMethod())
.Path(p.Pattern)
.ContentType(MediaType.ToString(MediaType.ApplicationJson))
.Description(p.Route.Description())
.Example(p.Route.Example())
).ToList());
support.AddMessageCodecSupport(MessageTransport.Http, () => Observable.Return(new HttpDeviceMessageCodec()));
support.AddConfigMetadata(MessageTransport.Http, _httpConfig);
return Observable.Return(support); } }
1. 添加协议说明文档如代码: support.AddDocument(MessageTransport.Http, "Document/document-http.md");,文档仅支持 markdown文件,如下所示
### 使用HTTP推送设备数据
上报属性例子:
POST /{productId}/{deviceId}/properties/report
Authorization:{产品或者设备中配置的Token}
Content-Type: application/json
{
"properties":{
"temp":11.5
}
}
上报事件例子:
POST /{productId}/{deviceId}/event/{eventId}
Authorization:{产品或者设备中配置的Token}
Content-Type: application/json
{
"data":{
"createtime": ""
}
}
2. 添加身份鉴权如代码: support.AddAuthenticator(MessageTransport.Http, new Demo5Authenticator()) ,自定义身份鉴权Demo5Authenticator 代码如下:
public class Demo5Authenticator : IAuthenticator
{
public IObservable<AuthenticationResult> Authenticate(IAuthenticationRequest request, IDeviceOperator deviceOperator)
{
var result = Observable.Return<AuthenticationResult>(default);
if (request is DefaultAuthRequest)
{
var authRequest = request as DefaultAuthRequest;
deviceOperator.GetConfig(authRequest.GetTransport()==MessageTransport.Http?"token": "key").Subscribe( config =>
{
var password = config.Convert<string>();
if (authRequest.Password.Equals(password))
{
result= result.Publish(AuthenticationResult.Success(authRequest.DeviceId));
}
else
{
result= result.Publish(AuthenticationResult.Failure(StatusCode.CUSTOM_ERROR, "验证失败,密码错误"));
}
});
}
else
result = Observable.Return<AuthenticationResult>(AuthenticationResult.Failure(StatusCode.CUSTOM_ERROR, "不支持请求参数类型"));
return result;
} public IObservable<AuthenticationResult> Authenticate(IAuthenticationRequest request, IDeviceRegistry registry)
{
var result = Observable.Return<AuthenticationResult>(default);
var authRequest = request as DefaultAuthRequest;
registry
.GetDevice(authRequest.DeviceId)
.Subscribe(async p => { var config= await p.GetConfig(authRequest.GetTransport() == MessageTransport.Http ? "token" : "key");
var password= config.Convert<string>();
if(authRequest.Password.Equals(password))
{
result= result.Publish(AuthenticationResult.Success(authRequest.DeviceId));
}
else
{
result= result.Publish(AuthenticationResult.Failure(StatusCode.CUSTOM_ERROR, "验证失败,密码错误"));
}
});
return result;
}
}
3. 添加Http路由代码support.AddRoutes,那么如何配置呢,代码如下:
public static BasicMessageCodec ReportProperty =>
new BasicMessageCodec("/*/properties/report", typeof(ReadPropertyMessage), route => route.GroupName("属性上报")
.HttpMethod("Post")
.Description("上报物模型属性数据")
.Example("{\"properties\":{\"属性ID\":\"属性值\"}}"));
4.添加消息编解码代码 support.AddMessageCodecSupport(MessageTransport.Http, () => Observable.Return(new HttpDeviceMessageCodec())), 可以自定义编解码,HttpDeviceMessageCodec代码如下:
public class HttpDeviceMessageCodec : DeviceMessageCodec
{
private readonly MessageTransport _transport; public HttpDeviceMessageCodec() : this(MessageTransport.Http)
{
} private static DefaultHttpResponseMessage Unauthorized(String msg)
{
return new DefaultHttpResponseMessage()
.ContentType(MediaType.ApplicationJson)
.Body("{\"success\":false,\"code\":\"unauthorized\",\"message\":\"" + msg + "\"}")
.Status(HttpStatus.AuthorizationFailed);
} private static DefaultHttpResponseMessage BadRequest()
{
return new DefaultHttpResponseMessage()
.ContentType(MediaType.ApplicationJson)
.Body("{\"success\":false,\"code\":\"bad_request\"}")
.Status(HttpStatus.RequestError);
} public HttpDeviceMessageCodec(MessageTransport transport)
{
_transport = transport;
}
public override IObservable<IDeviceMessage> Decode(MessageDecodeContext context)
{
if (context.GetMessage() is HttpRequestMessage)
{
return DecodeHttpRequestMessage(context);
}
return Observable.Return<IDeviceMessage>(default);
} public override IObservable<IEncodedMessage> Encode(MessageEncodeContext context)
{
return Observable.Return<IEncodedMessage>(default);
} private IObservable<IDeviceMessage> DecodeHttpRequestMessage(MessageDecodeContext context)
{
var result = Observable.Return<IDeviceMessage>(default);
var message = (HttpExchangeMessage)context.GetMessage(); Header? header = message.Request.GetHeader("Authorization");
if (header == null || header.Value == null || header.Value.Length == 0)
{
message
.Response(Unauthorized("Authorization header is required")).ToObservable()
.Subscribe(p => result = result.Publish(default)); return result;
}
var httpToken = header.Value[0]; var paths = message.Path.Split("/");
if (paths.Length == 0)
{
message.Response(BadRequest()).ToObservable()
.Subscribe(p => result = result.Publish(default));
return result;
}
String deviceId = paths[1];
context.GetDevice(deviceId).Subscribe(async deviceOperator =>
{
var config = deviceOperator==null?null: await deviceOperator.GetConfig("token");
var token = config?.Convert<string>();
if (token == null || !httpToken.Equals(token))
{
await message
.Response(Unauthorized("Device not registered or authentication failed"));
}
else
{
var deviceMessage = await DecodeBody(message, deviceId);
if (deviceMessage != null)
{
await message.Success("{\"success\":true,\"code\":\"success\"}");
result = result.Publish(deviceMessage);
}
else
{
await message.Response(BadRequest());
}
}
});
return result;
} private async Task<IDeviceMessage> DecodeBody(HttpExchangeMessage message,string deviceId)
{ byte[] body = new byte[message.Payload.ReadableBytes];
message.Payload.ReadBytes(body);
var deviceMessage = await TopicMessageCodec.Dodecode(message.Path, body);
deviceMessage.DeviceId = deviceId;
return deviceMessage;
}
}
5.添加元数据配置代码 support.AddConfigMetadata(MessageTransport.Http, _httpConfig); _httpConfig代码如下
private readonly DefaultConfigMetadata _httpConfig = new DefaultConfigMetadata(
"Http认证配置"
, "token为http认证令牌")
.Add("token", "token", "http令牌", StringType.Instance);
- 如何加载协议模块,协议模块包含了协议模块支持添加引用加载和上传热部署加载。
引用加载模块

上传热部署协议模块

四、设备网关
创建设备网关

五、产品管理
以下是添加产品。

设备接入

六、设备管理
添加设备

HTTP认证配置

创建告警阈值

七、测试
利用Postman 进行测试,以调用http://127.0.0.1:168/{productid}/{deviceid}/properties/report 为例,Authorization设置:123456
1.正常数据测试

2. 如果是选用Get方式调用,会因为找不到ServiceRoute而返回错误。

3. 把Authorization改成1111,会返回错误Device not registered or authentication failed,从而上报数据失败

以上上传的数据可以在设备信息-》运行状态中查看

告警信息可以在超临界数据中查看

七、总结
以上是基于HTTP网络组件设备接入,现有平台网络组件可以支持TCP,MQTT,UDP,CoAP,HTTP,Grpc,websocket,rtmp,httpflv,webservice,tcpclient, 而设备接入支持TCP,UDP,HTTP网络组件,后面会陆续添加支持所有网络组件接入,后面我也会陆续介绍其它网路组件设备接入 , 然后定于11月20日发布1.0测试版平台。也请大家到时候关注捧场。
基于surging 的木舟平台如何通过HTTP网络组件接入设备的更多相关文章
- 低代码平台--基于surging开发微服务编排流程引擎构思
前言 微服务对于各位并不陌生,在互联网浪潮下不是在学习微服务的路上,就是在使用改造的路上,每个人对于微服务都有自己理解,有用k8s 就说自己是微服务,有用一些第三方框架spring cloud, du ...
- 基于surging网络组件多协议适配的平台化发展
前言 Surging 发展已经有快6年的时间,经过这些年的发展,功能框架也趋于成熟,但是针对于商业化需求还需要不断的打磨,前段时间客户找到我想升级成平台化,针对他的需求我 ...
- 星舟平台的使用(GIT、spring Boot 的使用以及swagger组件的使用)
一.介绍星舟平台 1.星舟简介 2.网关kong的介绍 3.客户端 1).服务注册:Eureka 2).客户端负载均衡:Ribbon 4 ...
- Monotype推出基于HTML5的Web字体平台
著名字体公司Monotype近日宣布推出基于HTML5的Web字体平台,设计者可以访问近10万字体的目录. Monotype推出基于HTML5的Web字体平台 Monotype推出基于HTML5的We ...
- 基于AutoCAD的空间数据共享平台雏形
好久没有更新博客了,今天先透露一个新的产品——AutoMap.我自己对于这个产品的定位是“基于AutoCAD的空间数据共享平台”.用一句话来概括AutoMap的功能:为用户提供一个在AutoCAD下访 ...
- 基于React Native的移动平台研发实践分享
转载:http://blog.csdn.net/haozhenming/article/details/72772787 本文目录: 一.React Native 已经成为了移动前端技术的趋势 二.基 ...
- (二): 基于ZeroMQ的实时通讯平台
基于ZeroMQ的实时通讯平台 上篇:C++分布式实时应用框架 (Cpp Distributed Real-time Application Framework)----(一):整体介绍 通讯平台作为 ...
- 基于HttpRunner的接口自动化测试平台HttpRunnerManager(二)
https://github.com/HttpRunner/HttpRunnerManager HttpRunnerManager Design Philosophy 基于HttpRunner的接口自 ...
- 基于代码生成器的快速开发平台 JEECG
JEECG是一款基于代码生成器的J2EE快速开发平台,开源界“小普元”超越传统商业企业级开发平台.引领新的开发模式(Online Coding模式(在线开发)->代码生成器模式->手工ME ...
- nyoj 71-独木舟上的旅行(贪心)
71-独木舟上的旅行 内存限制:64MB 时间限制:3000ms 特判: No 通过数:10 提交数:15 难度:2 题目描述: 进行一次独木舟的旅行活动,独木舟可以在港口租到,并且之间没有区别.一条 ...
随机推荐
- ElementUI.Dialog.props怎么设置全局变量
在main.js中为啥?这个可以 ElementUI.Dialog.props.closeOnClickModal.default = false // 全局关闭点遮罩关闭弹框 为啥这个不可以? El ...
- 卷积神经网络CNN实战:MINST手写数字识别——网络定义
本文基于python-pytorch框架,编写CNN网络,并采用CNN手写数字数据集训练.测试网络. 网络的构建 以LeNet-5 网络为例 类定义 首先先了解一下网络的最基本框架 一般而言,首先创建 ...
- git使用问题记录
hint: Updates were rejected because the remote contains work that you do 问题原因: 远程仓库中含有本地仓库没有的文件 直接拉取 ...
- Session的运行机制
浏览器通过web访问服务器,服务器的web服务开启后,第一步就是开启session,这也是session的第一阶段: session_start() 这个函数的作用:开启session,然后根据以前设 ...
- JVM学习第二篇思考:一个Java代码是怎么运行起来的-下篇
JVM学习第二篇思考:一个Java代码是怎么运行起来的-下篇 在上一篇<JVM学习第一篇思考:一个Java代码是怎么运行起来的-上篇>中咱们知道类一个Java类的生命周期需要经历以下七个阶 ...
- Nuxt Kit 的使用指南:从加载到构建
title: Nuxt Kit 的使用指南:从加载到构建 date: 2024/9/12 updated: 2024/9/12 author: cmdragon excerpt: 摘要:本文详细介绍了 ...
- frp_v0.37.1内网穿透,内网服务公网用不求人
前言: 公司内网无法访问,出差又需要用到公司内网进行办公,苦恼了好一阵.这时候想到了内网穿透,这就不得不提到几年前被安利的frp,一看GitHub竟然已经5年了,网上估计大把教程了. 那么什么是frp ...
- SQL Server 备份方案
参考 SQL Server三种常见备份 SQL Server备份策略 以前写的笔记 目的 在发生意外 (人为删除, 磁盘坏掉) 之后, 让数据可还原到指定时间点上. Backup 的种类 备份分 3 ...
- Mybatis整合多数据源
背景 有时候我们需要查询来自多个库表的数据内容,但是又不想起多个服务,可以业务需要这些数据那该怎么办呢?那么其实Mybatis 是支持整合多数据源,并随时进行切换. 解决 引入依赖 首先引入dyn ...
- Windows 调试工具课程
本文是我在集团内部上的课程记录而成的博客内容.在本次课程里面将和大家介绍一些在 Windows 上常用的调试工具,以及调查问题的常见套路.适合于伙伴们入门 Windows 调试 本文以下内容是采用原本 ...