diff --git a/Waste.Application/ResultInfos/ResultService.cs b/Waste.Application/ResultInfos/ResultService.cs index fd92927..9629fe7 100644 --- a/Waste.Application/ResultInfos/ResultService.cs +++ b/Waste.Application/ResultInfos/ResultService.cs @@ -25,7 +25,7 @@ namespace Waste.Application private readonly ISuZhouService _suZhouService; private readonly IBusinessApiService _businessApiService; - public ResultService(ISqlSugarRepository sqlSugarRepository, ILoggerService loggerService, ISuZhouService suZhouService,IBusinessApiService businessApiService) + public ResultService(ISqlSugarRepository sqlSugarRepository, ILoggerService loggerService, ISuZhouService suZhouService, IBusinessApiService businessApiService) { repository = sqlSugarRepository; dbClient = repository.Context; @@ -165,6 +165,27 @@ namespace Waste.Application { isfrist = true; } + + if (myPackage.IsChecked && !string.IsNullOrEmpty(myPackage.Area) && myPackage.Area.Length > 0) + { + //新的协议中此字段为垃圾桶编号 + var areaBytes = Encoding.Default.GetBytes(myPackage.Area); + //长度为5个字节,后三位为垃圾桶编号(16进制) + if (areaBytes.Length == 5) + { + var typeBytes = new byte[3]; + for (var i = 0; i < 3; i++) + { + typeBytes[i] = areaBytes[i + 2]; + } + var typeHex = Convert.ToHexString(typeBytes); + myPackage.Area = Convert.ToInt32(typeHex, 16).ToString(); + //十六进制转10进制 + } + //000F000002.16进制 + var areaHex = Convert.ToHexString(areaBytes); + + } //记录数据 await dbClient.Ado.UseStoredProcedure().ExecuteCommandAsync("Proc_InsertResult", new { @@ -187,29 +208,39 @@ namespace Waste.Application isfrist = isfrist }); //上传垃圾数据 - if (myPackage.IsWeight && myPackage.Weight.ToDecimal() >0) - { - var devicesecret = await repository.Change().Context.Queryable().FirstAsync(x => x.DeviceId == device.Id); - if (devicesecret != null && !string.IsNullOrEmpty(devicesecret.Secret) - && !string.IsNullOrEmpty(devicesecret.SecretHash) - && !string.IsNullOrEmpty(devicesecret.DevId)) - { - int timestamp = GetTimestamp(time); - await _suZhouService.PostGarbagesAsync(new GarbagePltC2SDto - { - Weight = myPackage.Weight.ToDouble(), - secret = devicesecret.Secret, - secrethash = devicesecret.SecretHash, - ScanningTime = timestamp, - DStatus = 0, - deviceid = devicesecret.DevId, - Trash = "202101", - Type = TrashType(myPackage.WasteType) - }); - } - } + //if (myPackage.IsWeight && myPackage.Weight.ToDecimal() >0) + //{ + // var devicesecret = await repository.Change().Context.Queryable().FirstAsync(x => x.DeviceId == device.Id); + // if (devicesecret != null && !string.IsNullOrEmpty(devicesecret.Secret) + // && !string.IsNullOrEmpty(devicesecret.SecretHash) + // && !string.IsNullOrEmpty(devicesecret.DevId)) + // { + // int timestamp = GetTimestamp(time); + // await _suZhouService.PostGarbagesAsync(new GarbagePltC2SDto + // { + // Weight = myPackage.Weight.ToDouble(), + // secret = devicesecret.Secret, + // secrethash = devicesecret.SecretHash, + // ScanningTime = timestamp, + // DStatus = 0, + // deviceid = devicesecret.DevId, + // Trash = "202101", + // Type = TrashType(myPackage.WasteType) + // }); + // } + //} return new ResultInfo(ResultState.SUCCESS, "success"); } + + /// + /// byte转int + /// + /// + /// + private static int ByteToInt(byte bt) + { + return Convert.ToInt32(((int)bt).ToString("X2"), 16); + } private static int GetTimestamp(DateTime time) { DateTime dateTimeStart = TimeZoneInfo.ConvertTimeToUtc(new DateTime(1970, 1, 1, 8, 0, 0)); diff --git a/Waste.Application/Waste.Application.xml b/Waste.Application/Waste.Application.xml index 59e2e3d..2a292bd 100644 --- a/Waste.Application/Waste.Application.xml +++ b/Waste.Application/Waste.Application.xml @@ -1599,6 +1599,13 @@ + + + byte转int + + + + 角色信息提交 diff --git a/Waste.Doc/苏州垃圾分类计量设备计入标准/苏州市源头小区计量设备接入流程说明.doc b/Waste.Doc/苏州垃圾分类计量设备计入标准/苏州市源头小区计量设备接入流程说明.doc new file mode 100644 index 0000000..8c71bca --- /dev/null +++ b/Waste.Doc/苏州垃圾分类计量设备计入标准/苏州市源头小区计量设备接入流程说明.doc @@ -0,0 +1,738 @@ + + 《苏州市垃圾分类小区源头计量数据对接的规范流程》 + 为规范有序开展垃圾分类小区源头计量设备对接市级平台,现对接入流程作说明如 +下: +小区前端计量硬件设备参数以及数据对接的标准按照《苏州市垃圾分类信息化管理工作方 +案》(苏分办[2020] +16号)和《苏州市垃圾分类工作专报》(2021年第6期,总第28期)要求执行。 +小区垃圾分类计量设备数据需直接对接市平台,由各县市、区垃圾分类专班以工作联系 +单方式上报市垃圾分类专班,工作联系单需填写对接厂商硬件品牌、联系人、电话等信 +息,由市垃圾分类专班安排市级平台服务商提供对接服务,联系单格式详见附件一。 +市级平台服务商免费提供数据对接工作,每家硬件厂商可以在每个区域开通一个对接账 +号。 +为保障不同厂家的设备顺利接入及平台数据的安全及稳定性,现给出接入说明参考,见 +附件二;未预见之问题,双方配合协调解决。 +附件一 + + 苏州市垃圾分类前端计量设备数据接入工作联系单 + + 申请时间: 年 月 日 +|申请接入单位 | | +|设备安装区域 | | +|联系人 | |联系电话 | | +|邮箱 | | +|接入设备品牌 | | +|区域垃圾分类专班联| | +|系人/电话 | | +|区域垃圾分类专班意| | +|见(盖章) | | + + + + + + + + + + + +附件二 +苏州市垃圾分类源头计量设备接入说明 +当前测试平台地址为:https://bright.ljflytjl.cn:9101 (如有变动另行告知) + + + +目录 + +1、设备密钥获取及数据接口调试 2 +2、设备在线状态检测 18 +3、平台的安全及稳定性 22 + + + +使用者须知 +本平台从程序角度分为如下系统: +设备身份验证与授权开放平台(DSTS):用于管理设备的接入与在线状态,并向设备签 +发访问令牌(Access Token). +垃圾分类数据池平台:数据池平台用于接收存放各开发者及设备上传的数据内容。 +整个平台从角色定义角度,分为如下角色: +设备身份中间服务:即DSTS,该角色仅处理设备的身份验证与授权问题,并验证设备状 +态。不涉及具体的数据业务。 +设备:即实际物理设备,该角色被DSTS服务管理其在线状态,并签发访问令牌。 + +服务提供者:即数据池平台,设备由DSTS服务获得访问令牌之后,向数据池平台发起数 +据推送请求。 + + +1、设备密钥获取及数据接口调试 + +设备接入 + +开发者可在登录平台之后的开发者面板中管理自己的设备: +[pic] +设备需绑定到有效的采集点时,设备相关的API才可正常使用。 + +(测试平台的面板中未区分数据池平台和设备平台,因此将设备绑定到采集点的操作位 +于设备信息的编辑页面中,在正式平台的操作略有差异。) + + +[pic] + +数据池接入 + +数据概念 + +地产区域: 通常指一个商圈、一个小区等。 +采集点:地产区域中通常应包含至少一个采集点,如“清洁屋” + +在开发者面板的“采集点”和“地产区域”选项卡中,可以查看当前账户下的采集点和地产 +区域信息,如需添加等操作信息,请使用API进行操作。 + +API 接入指南 + +当前数据池平台以开发如下API接入形式 + • RESTFUL WebAPI (HTTPS) + +Web API验证 +向开发平台发起Web +API请求时,需要携带一些数据以确认请求者的身份并确保请求本身的安全性。 +Web API分为两种验证形式: + + 1. 开发者账号信息验证 + 2. 设备信息验证 + 具体使用哪种验证方式请查阅具体API的说明。 + 其中,两种API验证方式都需要以下验证数据: + +|数据项 |数据类型 |描述 |备注 | +|secret |Text |Secret Hash |该值由服务端生 | +| | | |成 | +|nonce |Number(int32) |流水号 |开发者需要确保 | +| | | |该值在2分钟内不| +| | | |重复,否则会被 | +| | | |拒绝请求 | +|sign |Text |数据签名Signatu|签名规则请见下 | +| | |re |方说明 | +|time |Number |UNIX时间戳 |请求发起时的时 | +| | | |间戳.如果时间不| +| | | |一致会导致请求 | +| | | |失败 | + +本系统采用标准UNIX时间戳,您的设备可连接至世界任意授时机构平台或使用GPS、北斗 +等卫星信号进行校时。 +开发者账号信息验证 + +使用开发者账号信息验证的API,在上述验证数据的基础上,需要如下数据: +|数据项 |数据类型 |描述 |备注 | +|user |Text |开发者账户ID |该值由服务端生 | +| | | |成 | + +我们可通过开发者面板的“开发者”选项卡中的“配置API信息”按钮来生成用于账号信息验 +证的相关数据。 + +[pic] + +其中“Api +Secret”为开发者自行设置,其长度不得小于8位,不得大于32位。打开页面时会随机生 +成一个字符串并填入。 + +[pic] +Api Secret原始值请在设置时妥善保管,丢失后无法找回。 +创建完成后,我们将在页面中得到需要的账户ID信息和Secret Hash信息: + +[pic] +Secret +Hash由开发者设置的Secret值通过一定方式计算得出,该计算过程不可逆且具有一定随 +机性,请以服务端计算结果为准,不要本地推算。 + + +设备信息验证 + +使用设备信息验证的API,在上述验证数据的基础上,需要如下数据: +|数据项 |数据类型 |描述 |备注 | +|device |Text |设备ID |该值由服务端生 | +| | | |成 | + +在添加或编辑设备时,开发者可以指定每个设备的Secret值,其规则与注意事项与开发 +者账号的Api Secret一致。 + +Web API验证方式 + +本平台Web API采用RESTFUL设计风格,对于GET、DELETE +等通常不在Body中携带参数的HTTP方法,将在HTTP请求header中验证所需的验证数据; +对于POST等通常在Body中携带参数的HTTP方法,将在HTTP请求的Body中验证所需的数据 +。 + +其中在不同的参数编排格式中,Body中传递的数据格式略有不同. + +Web Api请求签名规则 + +动态参数 : 将数据主体 内的所有必须字段的数据按照次序拼接为字符串。 + + 1. 获取动态参数字符串 + 2. + 在动态参数字符串后方拼接Secret(Hash之前的原始文本),得到新字符串,记作“ + Secret参数” + 3. 将Secret参数计算获取其小写16位MD5,得到签名 + +签名参数计算注意事项: + + 1. 可选参数不计入运算,此外备注中如有特殊标注的参数亦不计入运算。 + 2. + 在运算数字格式时,如数字无小数,请不要携带小数点后位数。(部分编程语言中, + float格式的10默认转字符串会得到"10.00",这会导致签名校验失败,应改为"10 + ") + + +[pic] + + +数据池接入案例指引 +下文演示时机编码接入本平台数据池平台,注意,该演示不包括设备平台(DSTS)在线 +验证部分。 +约定说明 + +本平台的消息格式约定如下: + +客户端请求DTO(Data Transfer +Object,即数据传输对象)中,数据以"Key/Value"形式编排. + +在一个在Body中携带了验证数据的典型POST方法请求中,数据的编排格式如下: + +--[[ + 使用开发者账号信息验证的API +]] +local body = { + "secret" = "a490080e777f453b", -- secret hash + "nonce" = 100, -- 流水号 + "sign" = "c720230e678c632e", -- 数据签名 + "time" = 1619845237, -- UNIX时间戳 + "user" = "9da14f23-766c-3357-bccd-2497463ac82c", -- 账户ID + "data" = { + -- 具体的数据内容 + "greet" = "Hello, Meow!" -- 这里的数据内容按顺序排序来计算数据签名 + } +} + + +--[[ + 使用设备信息验证的API +]] +local device_body = { + "secret" = "a490080e777f453b", -- 设备 secret hash + "nonce" = 100, -- 流水号 + "sign" = "c720230e678c632e", -- 数据签名 + "time" = 1619845237, -- UNIX时间戳 + "device" = "3fa85f64-5717-4562-b3fc-2c963f66afa6", -- 设备ID + "data" = { + -- 具体的数据内容 + "greet" = "Hello, Meow!" -- 这里的数据内容按顺序排序来计算数据签名 + } +} + +服务端向客户端返回的DTO中,数据通常不包含Key,以元组形式编排. + +示例 1 +package main + +import ( + "fmt" + "io/ioutil" + "net/http" + "strconv" + "time" +) + +func main() { + // apiSecret := "b1yUWkXZgrT1Of7t" + apiSecretHash := "88ee325fab0791d7" + userId := "8dd8c6e3-3634-4bc0-b523-9a0e29c7c40e" + currentTime := time.Now() + curTimeStamp := strconv.FormatInt(currentTime.Unix(), 10) + + //创建 http client + client := &http.Client{} + req, _ := http.NewRequest("GET", "https://bright.ljflytjl.cn:9101" + +"/api/Hello", nil) + + // 设置请求头 + req.Header.Set("Content-Type", "application/x-msgpack") //Content- +Type表示自己发送的资源类型 + req.Header.Set("Accept", "text/plain") //Accept表示希望请求到的资源类型 + req.Header.Set("secret", apiSecretHash) + req.Header.Set("nonce", "10") //实际请求中请确保流水号在两分钟内不重复 + req.Header.Set("time", curTimeStamp) + req.Header.Set("user", userId) + + //发送请求 + resp, err := client.Do(req) + if err != nil { + fmt.Println("Err:" + err.Error()) + } + + //最后关闭连接 + defer resp.Body.Close() + + //读取内容 + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + fmt.Println("解析内容出错" + err.Error()) + } + + fmt.Println("服务端返回:" + string(body)) +} + + +示例 2 +local M = {} +M.UserId = "8dd8c6e3-3634-4bc0-b523-9a0e29c7c40e"; +M.ApiSecret = "b1yUWkXZgrT1Of7t"; +M.ApiSecretHash = "88ee325fab0791d7"; + +--- 获取字符串格式的UTC Unix时间戳 +function M.GetUnixTimeStampStr() + return tostring(os.time(os.date("!*t"))); +end + +--- 获取数据签名 +function M.GetSignature(...) + local paramsStr = ""; + for i , v in ipairs({...}) do + paramsStr = paramsStr .. tostring(v); + end + local secretParams = paramsStr .. M.ApiSecret; + return CS.TinaX.EncryUtil.GetMD5(secretParams, true, true); -- +调用TinaX原生层Util +end + +function M.GetHelloWorld(greet) + if greet == nil or type(greet) ~= "string" then + error("greet is invalid.") + end + local md5 = M.GetSignature(greet); + local req = XCore.Http.MakeRequest({ + uri = "https://bright.ljflytjl.cn:9101/api/Hello/" .. greet, + header = { + { key = "Content-Type", value = "application/x-msgpack" }, + { key = "Accept", value = "application/x-msgpack" }, + { key = "secret", value = M.ApiSecretHash }, + { key = "nonce", value = 10 }, + { key = "time", value = M.GetUnixTimeStampStr()}, + { key = "sign", value = M.GetSignature(greet)}, + { key = "user", value = M.UserId} + } + }); + XCore.Http.GetAsync(req, function(resp, err) + -- onFinish callback + if err ~= nil then + error(err.Message) + end + print(resp:ReadAsString()); + end) +end + +return M; + +Swagger +由于API文档的完善工作量较大,为了让各开发者能够尽快入手开发,本系统临时开放S +wagger页面. + +Swagger页面地址为: https://bright.ljflytjl.cn:9101/swagger +(如有变动另行告知)相关事项说明如下: + + 1. 随着API文档的完善,Swagger页面随时关闭. + 2. + 由于Swagger是第三方工具,且默认不支持本平台内部设计的Dto描述格式,因此Sw + agger自动生成的内容可能与平台实际运作的API接口冲突,包括如下已知问题: + + + • 部分接口不会出现在Swagger页面上 + • Swagger页面的调试功能完全不可用 + • Swagger页面所描述的Media type与实际支持类型有出入 + • + Swagger页面所显示的Dto在部分数据格式下与实际返回内容不符,请以实际返回 + 内容为准。 + 3. Swagger仅供参考,实际请以API文档说明为准。 + 4. 使用Protocol + buffer格式接入时,按照swagger所呈现的dto格式编写.proto文件即可,版本为s + yntax = + "proto3";,本平台内部没有使用.proto文件描述协议,故不提供.proto参考文件 + 。 + + + + +[pic] + +测试接口 +本平台提供了几个无实际意义的Hello World API用于开发者的接入测试。 + +[GET] /api/Hello + + • 验证方式:账户信息验证 + • 验证传递形式:Header + • 参数: 无 + • 返回类型: Text + + + + +[pic] + +[GET] /api/Hello/{greet} + + • 验证方式:账户信息验证 + • 验证传递形式:Header +请求参数 +|key |类型 |可空 |签名验证 |说明 |备注 | +|greet |Text |false |1 |- | | + +返回类型: Text + + + +[pic] + +[POST] /api/Hello + + • 验证方式:账户信息验证 + • 验证传递形式:Body(DTO) + +请求参数 +|key |类型 |可空 |签名验证 |说明 |备注 | +|greet |Text |true |1 |- | | + +返回内容 +|key |类型 |索引顺序 |说明 |备注 | +|msg |Text |0 |- |返回文本 | +|code |Number |1 |- |固定返回 1 | + + +[pic] + + +地产区域API +[GET] /api/Estates + +分页查询当前账号下存在的地产区域数据。 + • 验证方式:账户信息验证 + • 验证传递形式:Header + +请求参数 +|key |类型 |可空 |签名验证 |说明 |备注 | +|page |Number |true |- |页索引 |Query Text | +| | | | | |Parameters | +|size |Number |true |- |每页数据 |Query Text | +| | | | |量 |Parameters | +|search |Number |true |- |搜索文本 |Query Text | +| | | | | |Parameters | + +返回内容: + +!> 范围内容位于分页封装结构中. +|key |类型 |索引顺序 |说明 |备注 | +|id |UUID |0 |地产区域ID |- | +|code |Text |1 |地产区域编 |- | +| | | |码 | | +|addr |Text |2 |地产区域所 |- | +| | | |在地址 | | +|city |Text |3 |城市编码 |例:3205000000| +| | | | |00(苏州) | +|area |Text |4 |区域编码 |例:3205070000| +| | | | |00(相城) | +|street |Text |5 |街道编码 |例:3205071050| +| | | | |00(渭塘镇) | + + + + +[pic] + +[POST] /api/Estates + +添加地产区域信息. + + • 验证方式:账户信息验证 + • 验证传递形式:Body(DTO) + +请求参数 +|key |类型 |可空 |签名验证 |说明 |备注 | +|code |Text |false |1 |地产区域 |开发者指定, | +| | | | |编码 |不可重复, 长 | +| | | | | |度限制2到32 | +|name |Text |false |2 |名称 |长度限制2到32| +|addr |Text |false |3 |地址 |长度限制4到12| +| | | | | |8 | +|city |Text |false |4 |城市编码 |例:320500000| +| | | | | |000(苏州) | +|area |Text |false |5 |区域编码 |例:320507000| +| | | | | |000(相城) | +|street |Text |false |6 |街道编码 |例:320507105| +| | | | | |000(渭塘镇)| + +返回内容: +|key |类型 |索引顺序 |说明 |备注 | +|id |UUID |0 |地产区域ID |- | +|code |Text |1 |地产区域编 |- | +| | | |码 | | +|addr |Text |2 |地产区域所 |- | +| | | |在地址 | | +|city |Text |3 |城市编码 |例:3205000000| +| | | | |00(苏州) | +|area |Text |4 |区域编码 |例:3205070000| +| | | | |00(相城) | +|street |Text |5 |街道编码 |例:3205071050| +| | | | |00(渭塘镇) | + + + + +[pic] + +[GET] /api/Estates/{Id} + +查询地产区域信息. + + • 验证方式:账户信息验证 + • 验证传递形式:Header + +请求参数 +|key |类型 |可空 |签名验证 |说明 |备注 | +|Id |UUID |false |1 |Id |Query Text | +| | | | | |Parameters | + +返回内容: +|key |类型 |索引顺序 |说明 |备注 | +|id |UUID |0 |地产区域ID |- | +|code |Text |1 |地产区域编 |- | +| | | |码 | | +|addr |Text |2 |地产区域所 |- | +| | | |在地址 | | +|city |Text |3 |城市编码 |例:3205000000| +| | | | |00(苏州) | +|area |Text |4 |区域编码 |例:3205070000| +| | | | |00(相城) | +|street |Text |5 |街道编码 |例:3205071050| +| | | | |00(渭塘镇) | + + +[pic] + +推送垃圾采集数据 API + +[POST] api/Garbages + +向服务端推送测试用垃圾采集数据. + +该接口仅供测试, 请自行备份保存相关数据。 + + • 验证方式:设备信息证 + • 验证传递形式:Body(DTO) + +请求参数 +|key |类型 |可空 |签名验证 |说明 |备注 | +|weight |Number |false |1 |垃圾称重 |64位浮点进| +| | | | |数据 |度,单位为| +| | | | | |千克 | +|trash |Text |false |2 |垃圾桶编 |- | +| | | | |码 | | +|type |Number |false |3 |垃圾类型 |- | +|scanningTime |Number |false |4 |数据扫描 |UNIX时间戳| +| | | | |时间 | | +|d_status |Number |false |5 |设备状态 |- | + +返回内容:HTTP状态码 + +垃圾类型说明 + +固定枚举类型: + + • 缺省类型 : 0 + • 厨余垃圾 : 1 + • 可回收物 : 2 + • 有害垃圾 : 3 + • 其他垃圾 : 4 + +尽量请勿传递缺省类型,以免影响系统对设备接入方稳定性的评估打分 + +设备状态说明 + + • 使用中 : 0 + • 异常 : 1 + • 检修 : 2 + • 检修结束 : 3 + • 启用 : 4 + • 未知 : 5 + + + +[pic] + + +2、设备在线状态检测 + +设备身份验证与授权开放平台接入 + +在平台标准环境中,设备应与设备身份验证与授权平台(下文简称DSTS)保持长连接状 +态。其中: + 1. 设备应是真实的物理设备,平台将会通过一定手段检测模拟设备 + 2. 设备在线状态将由DSTS管理 +验证码策略 + +平台将通过一定手段确保接入的设备是真实存在的而非程序模拟的虚假设备,当系统检 +测到设备有异样时,将执行验证码抽检策略,以确保设备的真实性。 +执行验证码抽检策略时,服务端将向设备(Client)主推验证码消息,对于具备完整操 +作系统的设备,(如 Windows CE,Linux, +Android等),验证码需调起Web引擎(如Chromium、Android +WebView等)跳转到DSTS平台下发的验证码页面并由人工完成验证码识别,其形式包括但 +不限于: + +图片辨识形式 +[pic] +滑动图块形式 +[pic] + +对于不具备完整操作系统、或不支持触屏输入的设备,验证码将以图片形式下发,操作 +人员使用后期开放的App进行验证码输入或扫码操作以完成验证码识别(对App使用诸如 +Xposed框架虚拟定位、模拟器、脱机外挂等操作可能会导致开发者账号被封禁)。 + +验证码策略的Web引擎 +对于有完备操作系统类型的设备,需要调起Web引擎进行设备验证等工作,本平台推荐使 +用最新版本的Chromium或Android +WebView作为参考标准,要求Web引擎具备以下能力: + 1. 跨域请求的兼容性 + 2. CSS3 + 3. SameSite Cookie跨域兼容性(请参考2020年主流浏览器对SameSite的新策略) + 4. JavaScript 运行环境 (ES 6 以上标准) + 5. WebAssembly 运行环境 (参考:https://developer.mozilla.org/zh- + CN/docs/WebAssembly) + 6. 使用前端接口获取设备信息、定位等权限 +禁止前端代码获取定位等信息可能导致验证策略不通过。 + +长连接 +设备应与DSTS平台建立长连接通讯,平台将使用长连接作为判断设备在线状态的依据, +并通过长连接向设备签发和更新Access Token. + +通讯协议 +本平台优先使用广泛流行的主流通讯协议,在当前版本中,本平台采用基于WebSocket和 +Http为基础约定的RPC通讯方式. + +设备计算验证规则 +在DSTS平台签发或更新Token前,平台会向设备随机发送一段脚本语言代码,设备需要在 +本机执行平台下发的代码,并向服务端返回代码运行结果以完成一次设备校验,如计算 +结果不符合预期,则不会下发Token. + +现阶段平台可下发的脚本语言包括: + 1. JavaScript (ES6) + 2. Lua 5.4 +在建立长连接时,设备端将与服务端沟通所支持的脚本语言类型。对于低算力设备,推 +荐使用Lua语言. + +脚本运行环境 +客户端的脚本语言运行环境需要实现如下全局方法,实际接口请以API文档为准: + +版本 1.0: +|方法 |说明 | +|LogInfo |向Log列表添加一行文本 | +|GetLocalIP |获取本机IP列表 | +|GetDeviceUniqueIdentifier |获取设备唯一ID | +|GetLocation |获取当前坐标信息、速度、 | +| |精度、TTFF等信息 | +|GetGPSInfo |获取当前GPS天线信号中GPS | +| |卫星ID、高度角、方位角等 | +| |信息的列表 | +|GetBDSInfo |获取当前北斗天线信号中北 | +| |斗卫星ID、高度角、方位角 | +| |等信息的列表 | +|GetMacAddress |获取本机Mac地址列表 | +|GetOSPlatform |获取操作系统信息 | +|GetCPUTemperature |获取CPU温度信息 | +|HttpRequest |对外发起Http请求 | +|GetSandboxIOPath |获取可读写的地址 | +|GetMD5 |计算md5 | +|GetSha256 |计算Sha256 | +|JsonEncode |Lua table 编码到 json文本| +| |(JavaScript运行时不需要 | +| |) | +|JsonDecode |json文本 解析到 Lua | +| |table(JavaScript运行时不| +| |需要) | +|MsgPackEncode |Lua table / JavaScript | +| |Object 编码到 | +| |MessagePack数据包 | +|MsgPackDecode |MessagePack数据包 解析到 | +| |Lua table / JavaScript | +| |Object | + + +特殊说明 + 1. + 对外发起Http请求的底层实现,如需代理请务必在本地代理。比如脚本代码向平台某 + 个端点发起Http请求时服务端得到的客户端IP与当前长连接IP不一致可能会导致校 + 验失败。 + 2. + 脚本代码可能会向平台之外的地址发起请求,如访问百度首页获取时间信息等,请避 + 免URL白名单设计。 + 3. + 脚本语言使用语言自带的方法获取系统时间(如lua使用os.time()),请确保脚本语 + 言vm的时钟是准确的。 + 4. + 不要求脚本语言环境实现全局I/O操作,但需要提供一个可读写的沙箱地址以供缓存 + 使用 + 5. + 每次执行脚本时,请重置脚本语言VM环境,确保上一次执行的代码不会影响本次执行 + 代码 + 6. 请尽可能不要频繁移动、旋转设备的GPS天线. + 7. + 出于安全性考虑,请隔离脚本语言运行环境,如不要让脚本语言可以反射调用原生层 + 代码,只注入约定的方法即可。 + 8. + 原则上平台要求设备提供真实的传感器数据,其中卫星定位信息是判断设备真实性的 + 重要依据,出于兼容性考虑,DSTS平台会向无法获取定位信息的设备下发签名,但 + 会影响平台对其的数据权重和可靠性评分。 + +[pic] + + +3、平台的安全与稳定性 + + +IP策略 +出于确保设备真实性的原则,平台要求设备公网IP理论上应当唯一,在此原则上,平台 +将考虑实际情况逐步实行包括但不限于以下策略: + 1. + IP记录和定位:后台将分析多个设备公用同一个IP向服务器发起请求、以及IP定位范 + 围与实际范围不一致的情况。 + 2. 主动握手抽检:平台将主动向该设备的当前在线IP发起不敏感端口的连接请求。 + 3. + 考虑到大陆地区IPv4公网资源不足,电信运营商广泛存在NAT共享公网IP,导致平台 + 无法主动握手抽检的前提环境下,平台将在未来逐步过渡到只信任设备IPv6接入来 + 源IP,和只提供IPv6原生访问接口的策略. + +测试环境与正式环境 +厂商设备在接入正式平台之前,应先接入测试平台,并在测试平台进行联调,确保数据 +及设备稳定之后方可接入正式平台。 +测试环境与正式环境存在如下差异或注意点: + 1. + 测试平台中所有端点(EndPoint)位于统一域名下,即“DSTS”与“数据池平台”感觉上 + 是一体的。但实际上它们从程序角度来说是两个系统,请开发者在设计时注意诸如 + 跨域访问等问题的兼容性,以免在接入分布式环境的正式平台时出现异常。 + 2. + 测试平台为方便厂商接入,在一定时机下会关闭设备在线验证等服务,即设备可随时 + 通过API推送数据到数据池服务,而不判断设备的在线状态。 + 3. + 测试平台为方便厂商接入,在一定时机下会关闭设备的真实性验证,如设备的区域与 + IP是否匹配等。 + 4. 测试服与正式服的数据不互通。 + +接口版本与长期支持版本 +线上网络系统会随着时间的推移、技术的变迁和外界环境的变更而不断演进,系统的接 +入方式和接口也会随着版本的更迭而逐渐变化。 +本文档标准为版本 1.0.0 ,在1.x +大版本下,系统的接入方式不会出现大变动,但会出现接口数据内容的微调。平台接口 +内容会持续迭代更新,但通常情况下,开发者可在请求中指定接口版本,如在Web +Api接口请求中,可通过在Header中添加协商版本号来请求指定开发版本的接口。 +平台将在2021年下半年推出1.x +大版本的长期支持版本,该版本保证至少18个月的长期维护。 +如有诸如“上级统一要求变更某种编号数据的格式”等强制要求,可能导致包括长期支持 +版本在内的版本接口提前结束服务。 diff --git a/Waste.Doc/苏州垃圾分类计量设备计入标准/附件三硬件标准.docx b/Waste.Doc/苏州垃圾分类计量设备计入标准/附件三硬件标准.docx new file mode 100644 index 0000000..33fdcb6 --- /dev/null +++ b/Waste.Doc/苏州垃圾分类计量设备计入标准/附件三硬件标准.docx @@ -0,0 +1,34 @@ +附件三:关于读卡器、垃圾桶芯片编码标准、设备编号标准 +1、由于垃圾桶在收运过程中存在流转现象,为规避读卡器不兼容的情况,建议读卡器的频率重点选择ISM915MHZ频段;并对垃圾桶芯片采用统一格式编码,要求如下: +(1)垃圾种类数据定义: +其它垃圾:30(16进制,1个字节) +厨余垃圾:31 +可回收垃圾:32 +有害垃圾:33 +(2)垃圾桶数据定义: +小桶:30(16进制,1个字节) +大桶:31 +编号:XX XX XX XX XX(16进制,5个字节,最大为FFFFFFFFFF=1099511627775即1万多亿) +一张卡片的卡片有效信息为:垃圾种类+桶种类+编号。如厨余垃圾小桶100号,数据格式为:31 30 00 00 00 00 64 +卡片数据完整为: +垃圾桶编号 +垃圾桶编号 +厂家预留 +厂家预留 +桶大小 +桶大小 +垃圾种类 +垃圾种类 +00 00 00 00 00 31 30 00 00 00 00 64 + + +厂家预留(红字),其中后二位由平台服务商提供,前二位厂商使用需与平台服务商沟通,确认之后使用,避免重复。 + +2、为直观区分各厂家设备,对全市设备实行统一编码,编码规则如下: +格式:十进制,总长度9位,其中前两位为字母,并以H开头,由平台服务商提供厂家的字母编号,其余7位由设备厂商自行编码,厂商完成设备编码后,返回平台服务商进行备案。 + +HA 0000 170 +设备编号 +设备编号 +厂家编码 +厂家编码 diff --git a/Waste.Web.Entry/Properties/PublishProfiles/waste.ybhdmob.com.pubxml.user b/Waste.Web.Entry/Properties/PublishProfiles/waste.ybhdmob.com.pubxml.user index 6ae958f..a83c407 100644 --- a/Waste.Web.Entry/Properties/PublishProfiles/waste.ybhdmob.com.pubxml.user +++ b/Waste.Web.Entry/Properties/PublishProfiles/waste.ybhdmob.com.pubxml.user @@ -5,6 +5,6 @@ https://go.microsoft.com/fwlink/?LinkID=208121. <_PublishTargetUrl>D:\webpublish\waste.ybhdmob.com - True|2021-06-04T06:46:02.2707457Z;True|2021-06-02T15:08:52.8245632+08:00;True|2021-06-02T15:05:50.3614099+08:00;True|2021-06-02T14:59:32.3690948+08:00;True|2021-06-02T14:10:25.1182836+08:00;True|2021-06-02T14:09:54.9215833+08:00;True|2021-06-01T10:41:54.9488501+08:00;True|2021-06-01T10:38:56.0283198+08:00;True|2021-05-28T13:59:02.2308877+08:00;True|2021-05-28T11:56:26.6796406+08:00;True|2021-05-28T11:28:00.4087907+08:00;True|2021-05-27T16:18:09.5993838+08:00;True|2021-05-27T16:07:31.3484951+08:00;True|2021-05-27T11:30:37.9119310+08:00;True|2021-05-27T11:28:35.5374674+08:00;True|2021-05-27T08:00:09.1625592+08:00;True|2021-05-26T20:42:17.0852150+08:00;True|2021-05-26T20:36:49.7527415+08:00;True|2021-05-25T17:57:31.8791293+08:00;True|2021-05-25T13:49:29.6488978+08:00;True|2021-05-25T13:48:24.6686105+08:00;True|2021-05-25T13:25:41.2512493+08:00;True|2021-05-24T17:55:33.3800078+08:00;True|2021-05-20T14:35:30.6957985+08:00;True|2021-05-20T13:17:22.6192995+08:00;True|2021-05-20T10:51:38.1268169+08:00;True|2021-05-19T19:50:03.7000224+08:00;True|2021-05-19T19:44:27.2518811+08:00;True|2021-05-19T19:43:26.5916681+08:00;True|2021-05-19T19:36:29.3197365+08:00;True|2021-05-19T19:30:00.3802430+08:00;True|2021-05-19T17:55:23.7939835+08:00;True|2021-05-19T11:05:17.9043392+08:00;True|2021-05-19T10:19:38.4839988+08:00;True|2021-05-19T10:17:19.7430612+08:00;True|2021-05-19T10:13:23.0031721+08:00;True|2021-05-19T10:06:03.9881599+08:00;True|2021-05-18T14:39:03.8876574+08:00;True|2021-05-18T14:23:46.9818836+08:00;True|2021-05-18T14:19:56.2382079+08:00;True|2021-05-18T11:29:53.5497590+08:00;True|2021-05-18T11:16:18.0123853+08:00;True|2021-05-17T18:59:52.4159105+08:00;True|2021-05-17T18:53:37.9438984+08:00;True|2021-05-17T18:48:14.9625161+08:00;True|2021-05-17T17:46:03.7723404+08:00;True|2021-05-17T17:14:20.2312990+08:00;True|2021-05-17T16:44:34.5837616+08:00;True|2021-05-17T16:25:20.1087804+08:00;True|2021-05-17T11:35:27.9388562+08:00; + True|2021-06-11T00:16:29.9542894Z;True|2021-06-04T14:46:02.2707457+08:00;True|2021-06-02T15:08:52.8245632+08:00;True|2021-06-02T15:05:50.3614099+08:00;True|2021-06-02T14:59:32.3690948+08:00;True|2021-06-02T14:10:25.1182836+08:00;True|2021-06-02T14:09:54.9215833+08:00;True|2021-06-01T10:41:54.9488501+08:00;True|2021-06-01T10:38:56.0283198+08:00;True|2021-05-28T13:59:02.2308877+08:00;True|2021-05-28T11:56:26.6796406+08:00;True|2021-05-28T11:28:00.4087907+08:00;True|2021-05-27T16:18:09.5993838+08:00;True|2021-05-27T16:07:31.3484951+08:00;True|2021-05-27T11:30:37.9119310+08:00;True|2021-05-27T11:28:35.5374674+08:00;True|2021-05-27T08:00:09.1625592+08:00;True|2021-05-26T20:42:17.0852150+08:00;True|2021-05-26T20:36:49.7527415+08:00;True|2021-05-25T17:57:31.8791293+08:00;True|2021-05-25T13:49:29.6488978+08:00;True|2021-05-25T13:48:24.6686105+08:00;True|2021-05-25T13:25:41.2512493+08:00;True|2021-05-24T17:55:33.3800078+08:00;True|2021-05-20T14:35:30.6957985+08:00;True|2021-05-20T13:17:22.6192995+08:00;True|2021-05-20T10:51:38.1268169+08:00;True|2021-05-19T19:50:03.7000224+08:00;True|2021-05-19T19:44:27.2518811+08:00;True|2021-05-19T19:43:26.5916681+08:00;True|2021-05-19T19:36:29.3197365+08:00;True|2021-05-19T19:30:00.3802430+08:00;True|2021-05-19T17:55:23.7939835+08:00;True|2021-05-19T11:05:17.9043392+08:00;True|2021-05-19T10:19:38.4839988+08:00;True|2021-05-19T10:17:19.7430612+08:00;True|2021-05-19T10:13:23.0031721+08:00;True|2021-05-19T10:06:03.9881599+08:00;True|2021-05-18T14:39:03.8876574+08:00;True|2021-05-18T14:23:46.9818836+08:00;True|2021-05-18T14:19:56.2382079+08:00;True|2021-05-18T11:29:53.5497590+08:00;True|2021-05-18T11:16:18.0123853+08:00;True|2021-05-17T18:59:52.4159105+08:00;True|2021-05-17T18:53:37.9438984+08:00;True|2021-05-17T18:48:14.9625161+08:00;True|2021-05-17T17:46:03.7723404+08:00;True|2021-05-17T17:14:20.2312990+08:00;True|2021-05-17T16:44:34.5837616+08:00;True|2021-05-17T16:25:20.1087804+08:00;True|2021-05-17T11:35:27.9388562+08:00; \ No newline at end of file