diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..e5409b4a --- /dev/null +++ b/Dockerfile @@ -0,0 +1,8 @@ +FROM openjdk:11-jre-slim +WORKDIR /app +ADD iot-standalone/target/iot-standalone-0.4.0-SNAPSHOT.tar /app +ADD data/init /app/data/init +ADD data/components /app/data/components +ADD data/converters /app/data/converters +EXPOSE 8086 +ENTRYPOINT ["java", "-classpath", ".:lib/*","cc.iotkit.Application"] \ No newline at end of file diff --git a/data/components/3ababc5e-15e9-45a7-8f38-2a6afd45c780/component.js b/data/components/3ababc5e-15e9-45a7-8f38-2a6afd45c780/component.js new file mode 100644 index 00000000..2474c2d5 --- /dev/null +++ b/data/components/3ababc5e-15e9-45a7-8f38-2a6afd45c780/component.js @@ -0,0 +1,238 @@ +//api配置 +apiTool.config("127.0.0.1",8085,3000); + +this.onReceive=function(method,path,header,params,body){ + //method:post、get、delete... + //path:请求路径 + //header:http请求头数据,结构:{xx:xx,yy:yy} + //params:请求参数,结构:{xx:[...],yy:[...]} + //body:请求体,当提交的数据为json格式时使用,结构:{xx:xx,yy:yy} + apiTool.log("onReceive body:"+body); + var duHeader=body.header; + var namespace=duHeader.namespace; + var requestName=duHeader.name; + var messageId=duHeader.messageId; + var duPayload=body.payload; + var token=duPayload.accessToken; + var openUid=duPayload.openUid; + + //设备发现 + if(namespace=="DuerOS.ConnectedHome.Discovery" && requestName=="DiscoverAppliancesRequest"){ + var deviceIds=[]; + var discoveredDevices=[]; + var content={ + header:{ + namespace:"DuerOS.ConnectedHome.Discovery", + name:"DiscoverAppliancesResponse", + messageId:messageId, + payloadVersion:1 + }, + payload:{ + discoveredAppliances:discoveredDevices, + discoveredGroups:[{ + groupName:"客厅", + applianceIds:deviceIds, + groupNotes:"客厅分组控制", + additionalGroupDetails:{} + }] + } + }; + var rst=apiTool.getSpaceDevices(token); + apiTool.log(JSON.stringify(rst)); + if(rst && rst.status==200 && rst.data){ + var devices=rst.data; + for(var i in devices){ + var device=devices[i]; + var did=device.deviceId; + var pk=device.productKey; + var dn=device.deviceName; + + //更新设备openUid + rst=apiTool.setOpenUid(token,did,"dueros",openUid); + if(!rst || rst.status!=200){ + continue; + } + + //插座 + if(pk=="cGCrkK7Ex4FESAwe"){ + var powerstate=device.property.powerstate; + discoveredDevices.push({ + actions:["turnOn","turnOff"], + applianceTypes:["SOCKET"], + additionalApplianceDetails:{}, + applianceId:device.deviceId, + friendlyDescription:"智能插座", + friendlyName:device.name, + isReachable:device.online, + manufacturerName:"海曼", + modelName:"S1", + version:"v1.0", + attributes:[ + { + name:"客厅的插座", + scale:"", + timestampOfSample:0, + uncertaintyInMilliseconds:10 + }, + { + name:"connectivity", + value:"REACHABLE", + scale:"", + timestampOfSample:0, + uncertaintyInMilliseconds:10 + }, + { + name:"turnOnState", + value:powerstate==1?"ON":"OFF", + scale:"", + timestampOfSample:0, + uncertaintyInMilliseconds:10, + legalValue:"(ON, OFF)" + } + ] + }); + }else if(pk=="Rf4QSjbm65X45753"){ + //开关 + var powerstate=device.property.powerstate; + discoveredDevices.push({ + actions:["turnOn","turnOff"], + applianceTypes:["SWITCH"], + additionalApplianceDetails:{}, + applianceId:device.deviceId, + friendlyDescription:"智能开关", + friendlyName:device.name, + isReachable:device.online, + manufacturerName:"海曼", + modelName:"S1", + version:"v1.0", + attributes:[ + { + name:"客厅的开关", + scale:"", + timestampOfSample:0, + uncertaintyInMilliseconds:10 + }, + { + name:"connectivity", + value:"REACHABLE", + scale:"", + timestampOfSample:0, + uncertaintyInMilliseconds:10 + }, + { + name:"turnOnState", + value:powerstate==1?"ON":"OFF", + scale:"", + timestampOfSample:0, + uncertaintyInMilliseconds:10, + legalValue:"(ON, OFF)" + } + ] + }); + + } + } + } + + return { + url:"",//不指定直接作为响应返回 + header:{ + contentType:"application/json" + }, + content:JSON.stringify(content) + } + }else if(namespace=="DuerOS.ConnectedHome.Control"){ + //设备控制 + var appliance=duPayload.appliance; + var deviceId=appliance.applianceId; + var confirmName="UnsupportedOperationError"; + var rst={status:500}; + + //开关 + if(requestName=="TurnOnRequest"){ + //开 + confirmName="TurnOnConfirmation"; + rst=apiTool.setProperties(token,deviceId,{powerstate:1}); + }else if(requestName=="TurnOffRequest"){ + //关 + confirmName="TurnOffConfirmation"; + rst=apiTool.setProperties(token,deviceId,{powerstate:0}); + } + + if(rst.status!=200){ + confirmName="UnsupportedOperationError"; + apiTool.log("device control failed:"+JSON.stringify(rst)); + } + + var content={ + header: { + namespace: "DuerOS.ConnectedHome.Control", + name: confirmName, + messageId: messageId, + payloadVersion: "1" + }, + payload: { + "attributes": [] + } + }; + + return { + url:"", + header:{ + contentType:"application/json" + }, + content:JSON.stringify(content) + } + }else if(namespace=="DuerOS.ConnectedHome.Query"){ + //属性查询 + if(requestName=="ReportStateRequest"){ + var appliance=duPayload.appliance; + var deviceId=appliance.applianceId; + var property=appliance.attributeName; + var propertyVal=""; + var success=false; + if(property=="turnOnState"){ + //开关状态查询 + var rst= apiTool.getSpaceDeviceDetail(token,deviceId); + if(rst && rst.status==200 && rst.data.property){ + propertyVal=rst.data.property.powerstate==1?"ON":"OFF"; + success=true; + } + } + var content=success?{ + "header": { + "namespace": "DuerOS.ConnectedHome.Query", + "name": "ReportStateResponse", + "messageId": new Date().getTime()+"", + "payloadVersion": "1" + }, + "payload": { + "attributes": [ + { + "name": property, + "value": propertyVal, + "scale": "", + "timestampOfSample": new Date().getTime()/1000, + "uncertaintyInMilliseconds": 0 + } + ] + } + }:{}; + + return { + url:"", + header:{ + contentType:"application/json" + }, + content:JSON.stringify(content) + } + } + } + return { + url:"",//不指定直接作为响应返回 + header:{ + contentType:"application/json" + }, + content:"" + } +} \ No newline at end of file diff --git a/data/components/3ababc5e-15e9-45a7-8f38-2a6afd45c780/iot-http-biz-component-0.4.0-SNAPSHOT.jar b/data/components/3ababc5e-15e9-45a7-8f38-2a6afd45c780/iot-http-biz-component-0.4.0-SNAPSHOT.jar new file mode 100644 index 00000000..49a63eae Binary files /dev/null and b/data/components/3ababc5e-15e9-45a7-8f38-2a6afd45c780/iot-http-biz-component-0.4.0-SNAPSHOT.jar differ diff --git a/data/components/6c095554-35e7-4e9d-a8d2-bb919e9479f4/component.js b/data/components/6c095554-35e7-4e9d-a8d2-bb919e9479f4/component.js new file mode 100644 index 00000000..3109fa5f --- /dev/null +++ b/data/components/6c095554-35e7-4e9d-a8d2-bb919e9479f4/component.js @@ -0,0 +1,302 @@ +!function(n){"use strict";function d(n,t){var r=(65535&n)+(65535&t);return(n>>16)+(t>>16)+(r>>16)<<16|65535&r}function f(n,t,r,e,o,u){return d((u=d(d(t,n),d(e,u)))<>>32-o,r)}function l(n,t,r,e,o,u,c){return f(t&r|~t&e,n,t,o,u,c)}function g(n,t,r,e,o,u,c){return f(t&e|r&~e,n,t,o,u,c)}function v(n,t,r,e,o,u,c){return f(t^r^e,n,t,o,u,c)}function m(n,t,r,e,o,u,c){return f(r^(t|~e),n,t,o,u,c)}function c(n,t){var r,e,o,u;n[t>>5]|=128<>>9<<4)]=t;for(var c=1732584193,f=-271733879,i=-1732584194,a=271733878,h=0;h>5]>>>e%32&255);return t}function a(n){var t=[];for(t[(n.length>>2)-1]=void 0,e=0;e>5]|=(255&n.charCodeAt(e/8))<>>4&15)+r.charAt(15&t);return e}function r(n){return unescape(encodeURIComponent(n))}function o(n){return i(c(a(n=r(n)),8*n.length))}function u(n,t){return function(n,t){var r,e=a(n),o=[],u=[];for(o[15]=u[15]=void 0,16 -1 +} + +function getPkDn(clientId){ + var arr=clientId.split("_"); + return { + pk:arr[0], + dn:arr[1] + }; +} + +function auth(head,type,payload){ + if(isServerId(payload.clientid)){ + return { + type:"serverAuth", + data:{ + productKey:"pd", + deviceName:"dn", + } + }; + } + + + var arr= payload.clientid.split("_"); + if(arr.length<3){ + throw new Error("incorrect clientid:" + payload.clientid); + } + + var pk=arr[0]; + var dn=arr[1]; + var model=arr[2]; + var pwd=md5("xdkKUymrEGSCYWswqCvSPyRSFvH5j7CU"+payload.clientid); + if(pwd!=payload.password){ + throw new Error("incorrect password:" + pwd); + } + return { + type:"register", + data:{ + productKey:pk, + deviceName:dn, + model:model + } + }; +} + +function acl(head,type,payload){ + var _topic = payload.topic; + + if(isServerId(payload.clientid)){ + return { + type: "acl", + data:{ + productKey:"pd", + deviceName:"dn", + } + }; + } + + if (/^\/sys\/.+\/.+\/c\/#/i.test(_topic)) { + return subscribe(head,type,payload); + } + if (/^\/sys\/.+\/.+\/s\/.*/i.test(_topic)) { + return subscribe(head,type,payload); + } + +} + +function register(head,type,payload){ + var auth= payload; + var arr= auth.clientid.split("_"); + if(arr.length<3){ + throw new Error("incorrect clientid:" + auth.clientid); + } + + var pk=arr[0]; + var dn=arr[1]; + var model=arr[2]; + var pwd=md5("xdkKUymrEGSCYWswqCvSPyRSFvH5j7CU"+auth.clientid); + if(pwd!=auth.password){ + throw new Error("incorrect password:" + pwd); + } + return { + type:"register", + data:{ + productKey:pk, + deviceName:dn, + model:model + } + }; +} + +function subRegister(topic,parent, payload){ + if(!topic){ + throw new Error("topic is blank") + } + + + var params= payload.params; + + var reply= + { + productKey: parent.productKey, + deviceName: parent.deviceName, + mid: "0", + content:{ + topic: topic.replace("/s/","/c/")+"_reply", + payload: JSON.stringify({ + id: payload.id, + code: 0, + data: { + "productKey":params.productKey, + "deviceName":params.deviceName + } + }) + } + }; + + return { + type:"register", + data:{ + productKey:parent.productKey, + deviceName:parent.deviceName, + subDevices:[{ + productKey:params.productKey, + deviceName:params.deviceName, + model:params.model + }] + }, + action:{ + type:"ack", + content:JSON.stringify(reply) + } + }; +} + +function disconnect(head,type,payload){ + var clientId = payload.clientid + var device=getPkDn(clientId); + return { + type:"state", + data:{ + productKey:device.pk, + deviceName:device.dn, + state:"offline" + } + } +} + +function connect(head,type,payload) { + var clientId = payload.clientid + var device = getPkDn(clientId); + return { + type: "state", + data: { + productKey: device.pk, + deviceName: device.dn, + state: "online" + } + } +} + +function unsubscribe(head,type,payload){ + var topic = payload.topic; + + if(isServerId(payload.clientid)){ + return { + type: "acl", + data:{ + productKey:"pd", + deviceName:"dn", + } + }; + } + + var arr= topic.split('/'); + if(arr.length<6){ + throw new Error("incorrect topic: "+topic) + } + + var pk=arr[2]; + var dn=arr[3]; + + return { + type:"state", + data:{ + productKey: pk, + deviceName: dn, + state:"offline" + } + } +} + +function subscribe(head,type,payload){ + var topic = payload.topic; + + if(isServerId(payload.clientid)){ + return { + type: "acl", + data:{ + productKey:"pd", + deviceName:"dn", + } + }; + } + + var arr= topic.split('/'); + if(arr.length<6){ + throw new Error("incorrect topic: "+topic) + } + var pk=arr[2]; + var dn=arr[3]; + + return { + type: "state", + data: { + productKey: pk, + deviceName: dn, + state: "online" + } + } +} + + + + +var messageHandler = { + "/sys/client/connected":connect, + "/sys/client/disconnected":disconnect, + "/mqtt/auth":auth, + "/mqtt/acl":acl, + "/sys/session/subscribed":subscribe, + "/sys/session/unsubscribed":unsubscribe +} + +//必须提供onReceive方法 +this.onReceive=function(head,type,payload){ + payload=JSON.parse(payload); + + print("======================================================================= "); + print("【message from】: " + (isServerId(payload.clientid)?"Server":"Device") ); + print("onReceive head: "+JSON.stringify(head)); + print("onReceive type: "+JSON.stringify(type)); + print("onReceive payload: "+ JSON.stringify(payload)); + //print("onReceive compMqttClientIdList: "+ component.getCompMqttClientIdList()); + + var result = {}; + var topic = head.topic; + if(!topic) { + + print("【result】: " + JSON.stringify(result)); + print("======================================================================= "); + return result; + } + + var fun = messageHandler[topic]; + + + + if(fun){ + result = fun(head,type,payload) + } + else{ + var arr= topic.split('/'); + if(arr.length<6){ + throw new Error("incorrect topic: "+topic) + } + var pk=arr[2]; + var dn=arr[3]; + + //子设备注册 + if(topic.endsWith('/register')){ + result = subRegister(topic,{productKey:pk,deviceName:dn}, payload); + } + else { + //数据上报 + result = { + type: "report", + data: { + productKey: pk, + deviceName: dn, + mid: payload.id, + content: { + topic: topic, + payload: payload + } + } + } + } + + } + print("【result】: " + JSON.stringify(result)); + print("======================================================================= "); + return result; + +} + +this.onRegistered=function(regInfo,result){ +} \ No newline at end of file diff --git a/data/components/6c095554-35e7-4e9d-a8d2-bb919e9479f4/iot-emqx-component-0.4.0-SNAPSHOT.jar b/data/components/6c095554-35e7-4e9d-a8d2-bb919e9479f4/iot-emqx-component-0.4.0-SNAPSHOT.jar new file mode 100644 index 00000000..dce714c0 Binary files /dev/null and b/data/components/6c095554-35e7-4e9d-a8d2-bb919e9479f4/iot-emqx-component-0.4.0-SNAPSHOT.jar differ diff --git a/data/components/eabb131d-8fd1-43a8-88d9-a198abfd3d42/iot-mqtt-component-0.3.1-SNAPSHOT.jar b/data/components/eabb131d-8fd1-43a8-88d9-a198abfd3d42/iot-mqtt-component-0.4.0-SNAPSHOT.jar old mode 100755 new mode 100644 similarity index 94% rename from data/components/eabb131d-8fd1-43a8-88d9-a198abfd3d42/iot-mqtt-component-0.3.1-SNAPSHOT.jar rename to data/components/eabb131d-8fd1-43a8-88d9-a198abfd3d42/iot-mqtt-component-0.4.0-SNAPSHOT.jar index 6dfec6da..cb689706 Binary files a/data/components/eabb131d-8fd1-43a8-88d9-a198abfd3d42/iot-mqtt-component-0.3.1-SNAPSHOT.jar and b/data/components/eabb131d-8fd1-43a8-88d9-a198abfd3d42/iot-mqtt-component-0.4.0-SNAPSHOT.jar differ diff --git a/data/init/protocolComponent.json b/data/init/protocolComponent.json index 5c597fa6..b61abaca 100755 --- a/data/init/protocolComponent.json +++ b/data/init/protocolComponent.json @@ -1,47 +1,23 @@ [ - { - "id": "fee0e826-963f-4e53-a2cf-11e3e5f784ea", - "uid": "fa1c5eaa-de6e-48b6-805e-8f091c7bb831", - "name": "移动Onenet Studio接入", - "type": "biz", - "protocol": "http", - "jarFile": "http-biz-component-0.1.0-SNAPSHOT.jar", - "config": "{\"port\":\"8086\"}", - "converter": "6260396d67aced2696184053", - "state": "stopped", - "createAt": 1652238780184 - }, { "id": "eabb131d-8fd1-43a8-88d9-a198abfd3d42", "uid": "fa1c5eaa-de6e-48b6-805e-8f091c7bb831", "name": "MQTT标准协议组件", "type": "device", "protocol": "mqtt", - "jarFile": "iot-mqtt-component-0.3.1-SNAPSHOT.jar", + "jarFile": "iot-mqtt-component-0.4.0-SNAPSHOT.jar", "config": "{\"port\":1883,\"ssl\":false,\"type\":\"server\"}", "converter": "6260396d67aced2696184053", "state": "running", "createAt": 1650473458084 }, - { - "id": "cd8253c1-b489-434c-845d-d18c7b70dcea", - "uid": "fa1c5eaa-de6e-48b6-805e-8f091c7bb831", - "name": "电信NB协议接入组件", - "type": "device", - "protocol": "http", - "jarFile": "ctwing-component-0.2.1-SNAPSHOT.jar", - "config": "{\"port\":\"8087\"}", - "converter": "62995ba4dbf51a5ec41d5f7b", - "state": "stopped", - "createAt": 1654235056032 - }, { "id": "6c095554-35e7-4e9d-a8d2-bb919e9479f4", "uid": "fa1c5eaa-de6e-48b6-805e-8f091c7bb831", "name": "EMQX标准协议组件", "type": "device", "protocol": "mqtt", - "jarFile": "emqx-component-0.2.1-SNAPSHOT.jar", + "jarFile": "emqx-component-0.4.0-SNAPSHOT.jar", "config": "{\"port\":\"1884\",\"ssl\":false,\"type\":\"client\",\"subscribeTopics\":[\"/sys/+/+/s/#\",\"/sys/client/connected\",\"/sys/client/disconnected\",\"/sys/session/subscribed\",\"/sys/session/unsubscribed\"],\"authPort\":\"8088\",\"broker\":\"127.0.0.1\",\"clientId\":\"test\",\"username\":\"test\",\"password\":\"123\"}", "converter": "6260396d67aced2696184053", "state": "stopped", @@ -53,7 +29,7 @@ "name": "小度音箱接入组件", "type": "biz", "protocol": "http", - "jarFile": "http-biz-component-0.1.0-SNAPSHOT.jar", + "jarFile": "http-biz-component-0.4.0-SNAPSHOT.jar", "config": "{\"port\":\"8084\"}", "converter": "", "state": "stopped", diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 00000000..2a6dd8ad --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,17 @@ +version: '3.3' +services: + ui: + image: uncleregan/iotkit-ui:0.3.4 + container_name: iotkit-ce-ui + ports: + - 80:80 + links: + - iotkit:iotkit + iotkit: + image: iotkits/iotkit:0.4.0 + container_name: iotkit-cei + restart: on-failure + ports: + - 8086:8086 # API端口 + - 1883-1890:1883-1890 # 预留 + - 8000-8010:8000-8010 # 预留 \ No newline at end of file diff --git a/iot-components/iot-emqx-component/dependency-reduced-pom.xml b/iot-components/iot-emqx-component/dependency-reduced-pom.xml old mode 100755 new mode 100644 index 772bf05a..5af6fb55 --- a/iot-components/iot-emqx-component/dependency-reduced-pom.xml +++ b/iot-components/iot-emqx-component/dependency-reduced-pom.xml @@ -50,6 +50,8 @@ 11 11 + true + false @@ -97,5 +99,11 @@ 0.4.0-SNAPSHOT compile + + cc.iotkit + iot-data-service + 0.4.0-SNAPSHOT + compile + diff --git a/iot-components/iot-http-biz-component/dependency-reduced-pom.xml b/iot-components/iot-http-biz-component/dependency-reduced-pom.xml old mode 100755 new mode 100644 index 38bf4498..17259860 --- a/iot-components/iot-http-biz-component/dependency-reduced-pom.xml +++ b/iot-components/iot-http-biz-component/dependency-reduced-pom.xml @@ -46,7 +46,7 @@ org.projectlombok lombok - 1.18.22 + 1.18.24 compile diff --git a/iot-components/iot-mqtt-component/dependency-reduced-pom.xml b/iot-components/iot-mqtt-component/dependency-reduced-pom.xml new file mode 100644 index 00000000..d71f38e8 --- /dev/null +++ b/iot-components/iot-mqtt-component/dependency-reduced-pom.xml @@ -0,0 +1,101 @@ + + + + iot-components + cc.iotkit + 0.4.0-SNAPSHOT + + 4.0.0 + iot-mqtt-component + + + + maven-shade-plugin + 3.2.4 + + + package + + shade + + + + + + + io.vertx:vertx-core + io.vertx:vertx-mqtt + io.netty:netty-codec-mqtt + org.luaj:luaj-jse + + + + + + maven-compiler-plugin + + 11 + 11 + true + false + + + + + + + io.vertx + vertx-core + 4.2.2 + provided + + + io.vertx + vertx-mqtt + 4.2.2 + provided + + + io.netty + netty-codec-mqtt + 4.1.72.Final + provided + + + org.projectlombok + lombok + 1.18.24 + compile + + + org.slf4j + slf4j-api + 1.7.32 + compile + + + org.luaj + luaj-jse + 3.0.1 + provided + + + cc.iotkit + iot-common + 0.4.0-SNAPSHOT + compile + + + cc.iotkit + iot-component-base + 0.4.0-SNAPSHOT + compile + + + cc.iotkit + iot-data-service + 0.4.0-SNAPSHOT + compile + + +