Commit b12b1cae authored by 何金镒's avatar 何金镒

设备、场景 相关

parent 95f777a6
...@@ -115,3 +115,6 @@ ...@@ -115,3 +115,6 @@
} }
} }
``` ```
...@@ -112,6 +112,11 @@ ...@@ -112,6 +112,11 @@
<artifactId>TinyPinyin</artifactId> <artifactId>TinyPinyin</artifactId>
<version>2.0.3.RELEASE</version> <version>2.0.3.RELEASE</version>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
</dependencies> </dependencies>
<build> <build>
......
...@@ -2,14 +2,12 @@ package com.ikonke.konkeaialibabamcp.controller; ...@@ -2,14 +2,12 @@ package com.ikonke.konkeaialibabamcp.controller;
import cn.hutool.json.JSONArray; import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject; import cn.hutool.json.JSONObject;
import com.ikonke.konkeaialibabamcp.controller.param.AddSceneParam;
import com.ikonke.konkeaialibabamcp.service.SycDeviceService; import com.ikonke.konkeaialibabamcp.service.SycDeviceService;
import com.ikonke.konkeaialibabamcp.utils.KonkeIotUtils; import com.ikonke.konkeaialibabamcp.utils.KonkeIotUtils;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.util.List;
@Slf4j @Slf4j
...@@ -43,18 +41,10 @@ public class DeviceController { ...@@ -43,18 +41,10 @@ public class DeviceController {
@PostMapping("/addScene") @PostMapping("/addScene")
public String addScene(@RequestParam(value = "ccuName") String ccuName, public String addScene(@RequestParam(value = "ccuName") String ccuName,
@RequestParam(value = "ccuName")Integer roomId,
@RequestBody JSONObject actions) { @RequestBody JSONObject actions) {
log.info("addScene..新增场景..ccuName:{}",ccuName); log.info("addScene..新增场景..ccuName:{},actions:{}",ccuName,actions);
return konkeIotServer.addScene(ccuName,actions); return konkeIotServer.addScene(ccuName,actions);
} }
@PostMapping("/addScene2")
public String addScene2(@RequestParam(name = "ccuName") String ccuName,
@RequestBody JSONObject addSceneParam) {
log.info("addScene..新增场景..ccuName:{}",addSceneParam);
return konkeIotServer.addScene(ccuName,addSceneParam);
}
} }
...@@ -11,10 +11,13 @@ public class AddSceneParam { ...@@ -11,10 +11,13 @@ public class AddSceneParam {
private String name; private String name;
private Integer roomId; private Integer roomId;
private List<SceneAction> actions; private List<SceneAction> actions;
}
@Data
class SceneAction { @Data
public class SceneAction {
private Integer devId; private Integer devId;
private String typeId; private String typeId;
private Map<String, Object> operation; private Map<String, Object> operation;
}
} }
...@@ -186,4 +186,22 @@ public class SycDeviceService { ...@@ -186,4 +186,22 @@ public class SycDeviceService {
return "UNKNOWN"; return "UNKNOWN";
} }
public String getDeviceRealType(Integer oid){
String deviceModel_json_str = device_model_cache.get(String.valueOf(oid));
if(StrUtil.isBlank(deviceModel_json_str)){
QueryWrapper<DeviceModel> deviceModel_wrapper = new QueryWrapper<>();
deviceModel_wrapper.eq("operateId", oid);
List<DeviceModel> model_list = deviceModelService.list(deviceModel_wrapper);
if(!model_list.isEmpty()){
DeviceModel deviceModel = model_list.get(0);
device_model_cache.put(String.valueOf(oid), JSONUtil.toJsonStr(deviceModel));
return deviceModel.getRealType();
}
}else{
DeviceModel bean = JSONUtil.toBean(deviceModel_json_str, DeviceModel.class);
return bean.getRealType();
}
return "UNKNOWN";
}
} }
package com.ikonke.konkeaialibabamcp.utils;
import cn.hutool.core.util.StrUtil;
import java.awt.*;
public class ColorUtil {
public static Color getColor(String value){
if(StrUtil.isEmpty(value)){
return Color.white;
}
Color c = null;
switch (value){
case "Red":
c = Color.red;
break;
case "Yellow":
c = Color.yellow;
break;
case "Blue":
c = Color.blue;
break;
case "Green":
c = Color.green;
break;
case "White":
c = Color.white;
break;
case "Black":
c = Color.black;
break;
case "Cyan":
c = Color.cyan;
break;
case "Purple":
c = Color.magenta;
break;
case "Orange":
c = Color.orange;
break;
default:
c = Color.white;
break;
}
return c;
}
public static String getColorByRgb(int r,int g,int b){
Color c = new Color(r,g,b);
Color Violet = new Color(238,130,238);
Color Magenta = new Color( 255,0,255);
Color Indigo = new Color(75,0,130);
Color SlateBlue = new Color(106,90,205);
Color DarkBlue = new Color(0,0,139);
Color SkyBlue = new Color(135,206,235);
Color DarkCyan = new Color(0,139,139);
Color Beige = new Color(245,245,220);
Color Brown = new Color(165,42,42);
if(Color.red.equals(c)){
return "Red";
}else if(Color.yellow.equals(c)){
return "Yellow";
}else if(Color.blue.equals(c)){
return "Blue";
}else if(Color.green.equals(c)){
return "Green";
}else if(Color.white.equals(c)){
return "White";
}else if(Color.black.equals(c)){
return "Black";
}else if(Color.cyan.equals(c)){
return "Cyan";
}else if(Color.magenta.equals(c)){
return "Purple";
}else if(Color.orange.equals(c)){
return "Orange";
}else if(Color.PINK.equals(c)){
return "Pink";
}else if(Violet.equals(c)){
return "Violet";
}else if(Magenta.equals(c)){
return "Magenta";
}else if(Indigo.equals(c)){
return "Indigo";
}else if(SlateBlue.equals(c)){
return "SlateBlue";
}else if(DarkBlue.equals(c)){
return "DarkBlue";
}else if(SkyBlue.equals(c)){
return "SkyBlue";
}else if(DarkCyan.equals(c)){
return "DarkCyan";
}else if(Beige.equals(c)){
return "Beige";
}else if(Brown.equals(c)){
return "Brown";
}else{
float[] hsb = getHSBToRGB(r,g,b);
if(hsb[1] < 0.1 && hsb[2] > 0.9){
return "White";
}else if(hsb[2] < 0.1){
return "Black";
}
float deg = hsb[0]*360;
if (deg >= 0 && deg < 30){
return "Red";
} else if (deg >= 30 && deg < 90){
return "Yellow";
} else if (deg >= 90 && deg < 150){
return "Green";
}else if (deg >= 150 && deg < 210){
return "Cyan";
}else if (deg >= 210 && deg < 270){
return "Blue";
}else if (deg >= 270 && deg < 330){
return "Purple";
}else{
return "Red";
}
}
}
/**
* 根据RGB获取HSB
* @param red
* @param green
* @param blue
* @return HSB 0:色相(0~360,包括0和360) 1:饱和度(0~1,包括0和1) 2:亮度(0~1,包括0和1)
*/
public static float[] getHSBToRGB(int red,int green,int blue) {
if(red<0 || green<0 || blue<0){
//若rgb为负数,初始化为白色
red = 255;
green = 255;
blue = 255;
}
float[] hsbVals = new float[3];
Color.RGBtoHSB(red, green, blue, hsbVals);
hsbVals[0] = hsbVals[0]*360;
return hsbVals;
}
}
...@@ -8,6 +8,7 @@ import cn.hutool.json.JSONUtil; ...@@ -8,6 +8,7 @@ import cn.hutool.json.JSONUtil;
import com.ikonke.konkeaialibabamcp.constant.DeviceConstant; import com.ikonke.konkeaialibabamcp.constant.DeviceConstant;
import com.ikonke.konkeaialibabamcp.controller.param.AddSceneParam; import com.ikonke.konkeaialibabamcp.controller.param.AddSceneParam;
import com.ikonke.konkeaialibabamcp.entity.mongodb.DeviceStatus; import com.ikonke.konkeaialibabamcp.entity.mongodb.DeviceStatus;
import com.ikonke.konkeaialibabamcp.service.SycDeviceService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.MongoTemplate;
...@@ -16,7 +17,9 @@ import org.springframework.data.mongodb.core.query.Query; ...@@ -16,7 +17,9 @@ import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.awt.*;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
...@@ -35,9 +38,11 @@ public class KonkeIotUtils { ...@@ -35,9 +38,11 @@ public class KonkeIotUtils {
private String appKey; private String appKey;
private final MongoTemplate mongoTemplate; private final MongoTemplate mongoTemplate;
private final SycDeviceService sycDeviceService;
public KonkeIotUtils( MongoTemplate mongoTemplate) { public KonkeIotUtils(MongoTemplate mongoTemplate, SycDeviceService sycDeviceService) {
this.mongoTemplate = mongoTemplate; this.mongoTemplate = mongoTemplate;
this.sycDeviceService = sycDeviceService;
} }
public final static Map<String, String> actionMap = Map.of( public final static Map<String, String> actionMap = Map.of(
...@@ -549,25 +554,90 @@ public class KonkeIotUtils { ...@@ -549,25 +554,90 @@ public class KonkeIotUtils {
public String addScene(String ccuName,JSONObject scene){ public String addScene(String ccuName,JSONObject scene){
AddSceneParam bean = JSONUtil.toBean(scene, AddSceneParam.class); AddSceneParam bean = JSONUtil.toBean(scene, AddSceneParam.class);
JSONObject body = new JSONObject();
body.set("name", bean.getName());
body.set("roomId", bean.getRoomId());
JSONArray actions = new JSONArray();
for (AddSceneParam.SceneAction action : bean.getActions()) {
JSONObject body_action = new JSONObject();
body_action.set("id", action.getDevId());
body_action.set("realType",sycDeviceService.getDeviceRealType(Integer.valueOf(action.getTypeId())));
body_action.set("delay", 0);
body_action.set("operation", this.getSceneAction(action.getOperation()));
}
body.set("actions", actions);
String url = baseUrl + "/2.0/ccu/" + ccuName + "/scenes";
log.info("addScene..新增场景..ccuName:{},scene:{}",ccuName,scene.toString());
String result = HttpRequest.post(url)
.header("appId", appId)
.header("appKey", appKey)
.body(body.toString())
.execute().body();
// String url = baseUrl + "/2.0/ccu/" + ccuName + "/scenes"; log.info("addScene..新增场景..result:{}",result);
// log.info("addScene..新增场景..ccuName:{},scene:{}",ccuName,scene.toString()); JSONObject response = JSONUtil.parseObj(result);
// String result = HttpRequest.post(url) if(!response.getBool("success")){
// .header("appId", appId) throw new StatefulException(-1, response.getStr("message"));
// .header("appKey", appKey) }else{
// .body(scene.toString()) log.info("addScene..新增场景..result:{}",response.getStr("data"));
// .execute().body(); return response.getStr("data");
// }
// log.info("addScene..新增场景..result:{}",result); }
// JSONObject response = JSONUtil.parseObj(result);
// if(!response.getBool("success")){ /**
// throw new StatefulException(-1, response.getStr("message")); * 将大模型推荐的action转换成新增场景的action
// }else{ *
// return response.getStr("data"); */
// } public Object getSceneAction(Map<String, Object> operation){
if(operation.size()==1){
return ""; Map.Entry<String, Object> firstEntry = operation.entrySet().iterator().next();
String firstKey = firstEntry.getKey();
Object firstValue = firstEntry.getValue();
if("on".equalsIgnoreCase(firstKey)){
return firstValue;
}else{
log.error("不支持的操作1:{}",JSONUtil.toJsonStr(operation));
}
}else{
JSONObject jsonObject = new JSONObject();
for (String key : operation.keySet()){
if("bri".equalsIgnoreCase(key)){
jsonObject.set("bri", operation.get(key));
}else if("on".equalsIgnoreCase(key)){
jsonObject.set("on", operation.get(key));
}else if("colour_temperature".equalsIgnoreCase(key)){
jsonObject.set("colour_temperature", operation.get(key));
}else if("move_to_angle".equalsIgnoreCase(key)){
jsonObject.set("move_to_angle", operation.get(key));
} else if("move_to_pos".equalsIgnoreCase(key)){
jsonObject.set("move_to_pos", operation.get(key));
}else if("white_bri".equalsIgnoreCase(key)){
jsonObject.set("white_bri", operation.get(key));
}else if("rgb".equalsIgnoreCase(key)){
Color c = ColorUtil.getColor((String) operation.get(key));
Map<String,Object> rgbMap = new HashMap<>();
rgbMap.put("Red",c.getRed());
rgbMap.put("Green",c.getGreen());
rgbMap.put("Blue",c.getBlue());
jsonObject.set("rgb", rgbMap);
}else if("speed".equalsIgnoreCase(key)){
jsonObject.set("speed", operation.get(key));
}else if("runModel".equalsIgnoreCase(key)){
jsonObject.set("runModel", operation.get(key));
}else if("runTemp".equalsIgnoreCase(key)){
jsonObject.set("runTemp", operation.get(key));
}else{
log.error("不支持的操作2:{}",JSONUtil.toJsonStr(operation));
}
}
return jsonObject;
}
return null;
} }
/** /**
......
package com.ikonke.konkeaialibabamcp.utils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
@Component
public class RedisCacheUtil {
private final RedisTemplate<String, Object> redisTemplate;
public RedisCacheUtil(RedisTemplate<String, Object> redisTemplate) {
this.redisTemplate = redisTemplate;
}
public void set(String key, Object value, long timeout, TimeUnit unit) {
redisTemplate.opsForValue().set(key, value, timeout, unit);
}
public Object get(String key) {
return redisTemplate.opsForValue().get(key);
}
}
spring:
datasource:
type: com.zaxxer.hikari.HikariDataSource
url: jdbc:mysql://172.24.20.206:3306/ai_alibaba?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&allowMultiQueries=true&tinyInt1isBit=false&allowLoadLocalInfile=true&allowLocalInfile=true&allowUrl
username: hj
password: hj45aDIF!$
driver-class-name: com.mysql.cj.jdbc.Driver
data:
mongodb:
uri: mongodb://172.24.60.175:27017/konke_iot?authSource=konke_iot
redis:
password: kknjredis
lettuce:
pool:
max-active: 8 # 连接池中的最大空闲连接
max-wait: 500 # 连接池最大阻塞等待时间(使用负值表示没有限制)
max-idle: 8 # 连接池最大连接数(使用负值表示没有限制)
min-idle: 0 # 连接池中的最小空闲连接
cluster:
max-redirects: 3
nodes: 172.17.14.1:7001,172.17.14.1:7002,172.17.14.1:7003,172.17.14.2:7001,172.17.14.2:7002,172.17.14.2:7003
ai:
mcp:
server:
name: konke-ai-alibaba-mcp-server
version: 0.0.1
type: ASYNC # Recommended for reactive applications
sse-endpoint: /sse
sse-message-endpoint: /mcp
capabilities:
tool: true
resource: true
prompt: true
completion: true
mybatis-plus:
mapper-locations: classpath*:/mapper/**/*.xml
type-aliases-package: com.ikonke.konkeaialibabamcp.entity.mysql
logging:
level:
root: info
file:
path: ./log/${server.port}
pattern:
file: '%d{yyyy/MM/dd HH:mm:ss.SSS} %-5level [%X{traceId:-}][%thread] %logger{15} : %msg%n'
console: '%d{yyyy/MM/dd HH:mm:ss.SSS} %clr(%-5level) [%X{traceId:-}][%magenta(%thread)] %cyan(%logger{15}) : %msg%n'
logback:
rollingpolicy:
max-history: 30
konke:
weather:
clientId: da4c19db2be64671
deviceCloud:
appId: 10001319
appKey: 216531bf-6394-455d-98c0-87d74ad2fcc5
baseUrl: http://172.24.10.11:16000
cdc:
timeout: 20000
url: http://community.jfzhtest.com/prod-api
getOwnerUrl: ${cdc.url}/system/screen/owner/info
getListSpacesRoomUrl: ${cdc.url}/third/screen/spaces/rooms
getSpacesRoomDetailUrl: ${cdc.url}/third/screen/spaces/room/
getSpacesRoomBookingUrl: ${cdc.url}/third/screen/spaces/room/times
bookingSpacesRoomUrl: ${cdc.url}/third/mini/record
spacesRoomOrderUrl: ${cdc.url}/third/screen/spaces/order/submit
spacesCoupons:
getSpacesCouponsListUrl: ${cdc.url}/third/screen/spaces/coupons/all
receiveSpacesCouponsUrl: ${cdc.url}/third/screen/spaces/coupons/
getUserCouponsUrl: ${cdc.url}/third/screen/spaces/coupons/user
oneClickClaimCouponUrl: ${cdc.url}/third/screen/spaces/coupons/once
spring:
datasource:
type: com.zaxxer.hikari.HikariDataSource
url: jdbc:mysql://172.17.3.7:3306/ai_alibaba?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&allowMultiQueries=true&tinyInt1isBit=false&allowLoadLocalInfile=true&allowLocalInfile=true&allowUrl
username: root
password: RbNosaRd9)?_xKG9
driver-class-name: com.mysql.cj.jdbc.Driver
data:
mongodb:
uri: mongodb://user002:konke2025@172.17.13.1:27017,172.17.13.2:27017,172.17.13.3:27017/konke_iot?authSource=konke_iot&authMechanism=SCRAM-SHA-1
ai:
mcp:
server:
name: konke-ai-alibaba-mcp-server
version: 0.0.1
type: ASYNC # Recommended for reactive applications
sse-endpoint: /sse
sse-message-endpoint: /mcp
capabilities:
tool: true
resource: true
prompt: true
completion: true
mybatis-plus:
mapper-locations: classpath*:/mapper/**/*.xml
type-aliases-package: com.ikonke.konkeaialibabamcp.entity.mysql
logging:
level:
root: info
file:
path: ./log/${server.port}
pattern:
file: '%d{yyyy/MM/dd HH:mm:ss.SSS} %-5level [%X{traceId:-}][%thread] %logger{15} : %msg%n'
console: '%d{yyyy/MM/dd HH:mm:ss.SSS} %clr(%-5level) [%X{traceId:-}][%magenta(%thread)] %cyan(%logger{15}) : %msg%n'
logback:
rollingpolicy:
max-history: 30
konke:
weather:
clientId: da4c19db2be64671
deviceCloud:
appId: 10001304
appKey: 0c350d82-aa95-46e1-91b8-b8d508b5226a
baseUrl: http://172.17.12.6:10000
cdc:
timeout: 20000
url: http://community.jfzhtest.com/prod-api
getOwnerUrl: ${cdc.url}/system/screen/owner/info
getListSpacesRoomUrl: ${cdc.url}/third/screen/spaces/rooms
getSpacesRoomDetailUrl: ${cdc.url}/third/screen/spaces/room/
getSpacesRoomBookingUrl: ${cdc.url}/third/screen/spaces/room/times
bookingSpacesRoomUrl: ${cdc.url}/third/mini/record
spacesRoomOrderUrl: ${cdc.url}/third/screen/spaces/order/submit
spacesCoupons:
getSpacesCouponsListUrl: ${cdc.url}/third/screen/spaces/coupons/all
receiveSpacesCouponsUrl: ${cdc.url}/third/screen/spaces/coupons/
getUserCouponsUrl: ${cdc.url}/third/screen/spaces/coupons/user
oneClickClaimCouponUrl: ${cdc.url}/third/screen/spaces/coupons/once
server:
port: 9998
spring: spring:
datasource: profiles:
type: com.zaxxer.hikari.HikariDataSource active: prod
url: jdbc:mysql://172.17.3.7:3306/ai_alibaba?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&allowMultiQueries=true&tinyInt1isBit=false&allowLoadLocalInfile=true&allowLocalInfile=true&allowUrl
username: root
password: RbNosaRd9)?_xKG9
driver-class-name: com.mysql.cj.jdbc.Driver
data:
mongodb:
uri: mongodb://user002:konke2025@172.17.13.1:27017,172.17.13.2:27017,172.17.13.3:27017/konke_iot?authSource=konke_iot&authMechanism=SCRAM-SHA-1
ai:
mcp:
server:
name: konke-ai-alibaba-mcp-server
version: 0.0.1
type: ASYNC # Recommended for reactive applications
sse-endpoint: /sse
sse-message-endpoint: /mcp
capabilities:
tool: true
resource: true
prompt: true
completion: true
mybatis-plus:
mapper-locations: classpath*:/mapper/**/*.xml
type-aliases-package: com.ikonke.konkeaialibabamcp.entity.mysql
logging: server:
level: address: 0.0.0.0
root: info port: 9998
file:
path: ./log/${server.port}
pattern:
file: '%d{yyyy/MM/dd HH:mm:ss.SSS} %-5level [%X{traceId:-}][%thread] %logger{15} : %msg%n'
console: '%d{yyyy/MM/dd HH:mm:ss.SSS} %clr(%-5level) [%X{traceId:-}][%magenta(%thread)] %cyan(%logger{15}) : %msg%n'
logback:
rollingpolicy:
max-history: 30
konke:
weather:
clientId: da4c19db2be64671
deviceCloud:
appId: 10001304
appKey: 0c350d82-aa95-46e1-91b8-b8d508b5226a
baseUrl: http://172.17.12.6:10000
cdc:
timeout: 20000
url: http://community.jfzhtest.com/prod-api
getOwnerUrl: ${cdc.url}/system/screen/owner/info
getListSpacesRoomUrl: ${cdc.url}/third/screen/spaces/rooms
getSpacesRoomDetailUrl: ${cdc.url}/third/screen/spaces/room/
getSpacesRoomBookingUrl: ${cdc.url}/third/screen/spaces/room/times
bookingSpacesRoomUrl: ${cdc.url}/third/mini/record
spacesRoomOrderUrl: ${cdc.url}/third/screen/spaces/order/submit
spacesCoupons:
getSpacesCouponsListUrl: ${cdc.url}/third/screen/spaces/coupons/all
receiveSpacesCouponsUrl: ${cdc.url}/third/screen/spaces/coupons/
getUserCouponsUrl: ${cdc.url}/third/screen/spaces/coupons/user
oneClickClaimCouponUrl: ${cdc.url}/third/screen/spaces/coupons/once
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment