why to do:
  我之前一直很喜欢智能家居,可惜的是现在市场上成品的智能家居实在是太贵了,屌丝的码农是在背不起每月高额的房贷和装修费用的基础上,再买成品的智能设备(像某米那样一个智能开关,竟然卖那么贵,小弟实在是承受不起啊)。
  我现在想的很简单,就是家里的窗帘(每个卧室一个,客厅做一个双轨)、灯的开关、厨房的凉霸、还有几处插座面板做成智能的,然后在入户门口做个按钮就是按一下可以关闭屋内所有的灯。
  
  服务器:我之前买了一个群辉,用群辉中docker做的homeassistant
  窗帘电机:我从瀚思彼岸上买的,感觉价格挺实惠*5
  主灯:我买的yeelight,感觉在灯里面的价格还是挺靠谱的,主要他的开关可以调光,这个我很喜欢
  射灯:这块用的也是瀚思彼岸上买的开关
  插座开关:因为我在装修的时候把插座放到了电视后面,我这就做了个智能开关(2个),主要还得控制机顶盒还有我的高清视频播放器
  天猫精灵(去年双十一屯了几个方糖)
  由于新家还没有装修完,我这边就先做了个简单试验,把系统中基本的功能做完了,后期装修完成了,再好好弄弄,但是目前天猫精灵和homeassistant对接,网上确实有不少,可我是一个java码农,虽说对php了解的也还可以,但是肯定不如java啊,这个确实就比较少了,所以我在这里简单写写吧,希望java小伙伴们,可以多多提出建议哈。

how to do:
  天猫精灵有自己的开放平台:https://open.aligenie.com/
  1.添加技能  

  这个可以参考天猫精灵给的文档,我觉得写得挺简单的。
  我这边就提出几个比较重要的点,说一下吧:
  1.需要域名和https的证书(可以在阿里云上购买,证书有一个免费一年的)
  2.自己搭建的中转服务需要在外网访问
  3.homeassistant也需要在外网能访问,这里我自己打了一套ngrok,感觉效果还是不错的
  4.java方面,我用的spring boot这里写一些关键的,这个就是
  OAuth2SecurityConfiguration

@Order(1)
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class OAuth2SecurityConfiguration extends WebSecurityConfigurerAdapter {@Autowiredprivate ClientDetailsService clientDetailsService;@Autowiredprivate RedisConnectionFactory redisConnection;@Autowiredprivate BootUserDetailService userDetailService;@Overrideprotected void configure(HttpSecurity http) throws Exception {http// 必须配置,不然OAuth2的http配置不生效----不明觉厉.requestMatchers().antMatchers(  "/test/**","/auth/login","/auth/authorize","/oauth/**","/plugs/**","/gate").and().authorizeRequests()// 自定义页面或处理url是,如果不配置全局允许,浏览器会提示服务器将页面转发多次.antMatchers("/test/**","/auth/login","/plugs/**","/gate").permitAll().anyRequest().authenticated().and().csrf().disable();//跨域关闭// 表单登录http.formLogin()// 登录页面.loginPage("/auth/login")// 登录处理url.loginProcessingUrl("/auth/authorize");}@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.userDetailsService(userDetailService);}@Override@Beanpublic AuthenticationManager authenticationManagerBean() throws Exception {return super.authenticationManagerBean();}@Override@Beanpublic AuthenticationManager authenticationManager() throws Exception {return super.authenticationManager();}@Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}}

AuthorizationServerConfiguration


@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {@Autowiredprivate AuthenticationManager authenticationManager;/*** 保存令牌数据栈*/@Autowiredprivate TokenStore tokenStore;@Autowiredprivate PasswordEncoder passwordEncoder;@Autowiredprivate BootUserDetailService userDetailService;@Overridepublic void configure(AuthorizationServerSecurityConfigurer security) throws Exception {// 允许表单登录security.allowFormAuthenticationForClients();}@Overridepublic void configure(ClientDetailsServiceConfigurer clients) throws Exception {String secret = passwordEncoder.encode("*******");clients.inMemory() // 使用in-memory存储.withClient("client")// client_id.secret(secret)// client_secret.authorizedGrantTypes("refresh_token", "authorization_code")// 该client允许的授权类型.redirectUris("https://open.bot.tmall.com/oauth/callback").accessTokenValiditySeconds(60*60*24)//token过期时间.refreshTokenValiditySeconds(60*60*24)//refresh过期时间.scopes("all");// 允许的授权范围}@Overridepublic void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {endpoints.authenticationManager(authenticationManager).tokenStore(tokenStore).userDetailsService(userDetailService);endpoints.pathMapping("/oauth/confirm_access","/custom/confirm_access");}@Beanpublic TokenStore tokenStore(RedisConnectionFactory redisConnectionFactory) {// return new InMemoryTokenStore(); //使用内存存储令牌 tokeStorereturn new RedisTokenStore(redisConnectionFactory);//使用redis存储令牌}}

HassIntegerFaceController(和homeassitant交互)

public class HassIntegerFaceController {@Value("${kyz.hassLongToken}")private String hassLongToken;@Value("${kyz.hassUrl}")private String hassUrl;@Beanpublic RestTemplate restTemplate(RestTemplateBuilder builder) {// Do any additional configuration herereturn builder.build();}@Autowiredprivate RestTemplate restTemplate;@Autowiredprivate RedisUtil redisUtil;@Autowired()private UserService userService;@RequestMapping(value = "/add", method = RequestMethod.GET)public String add() {return getDeviceInfo().toString();}/*** 获取设备列表** @return*/public List<Map<String, Object>> getDeviceInfo() {// header填充RequestCallback requestCallback = getRequestCallback();ResponseExtractor<ResponseEntity<JSONArray>> responseExtractor = restTemplate.responseEntityExtractor(JSONArray.class);// 执行execute(),发送请求ResponseEntity<JSONArray> response = restTemplate.execute(hassUrl + "/api/states", HttpMethod.GET, requestCallback, responseExtractor);JSONArray jsonArray = response.getBody();JSONArray jsonArrayCover = new JSONArray();Map<String, Object> haDevice = new HashMap<>();List<Map<String, Object>> haDeviceList = new ArrayList<>();for (int i = 0; i < jsonArray.size(); i++) {JSONObject temp = jsonArray.getJSONObject(i);if (temp.getString("entity_id").startsWith("cover")) {jsonArrayCover.add(jsonArray.getJSONObject(i));haDevice = new HashMap<>();haDevice.put("deviceId", temp.getString("entity_id"));haDevice.put("friendly_name", temp.getJSONObject("attributes").getString("friendly_name"));haDevice.put("type", temp.getString("cover"));haDevice.put("state", temp.getString("state"));haDevice.put("deviceType", "curtain");redisUtil.set("ha_state_" + temp.getString("entity_id"), temp.getString("state"));haDeviceList.add(haDevice);}if (temp.getString("entity_id").startsWith("switch")) {jsonArrayCover.add(jsonArray.getJSONObject(i));haDevice = new HashMap<>();haDevice.put("deviceId", temp.getString("entity_id"));haDevice.put("friendly_name", temp.getJSONObject("attributes").getString("friendly_name"));haDevice.put("type", temp.getString("switch"));haDevice.put("state", temp.getString("state"));haDevice.put("deviceType", "switch");redisUtil.set("ha_state_" + temp.getString("entity_id"), temp.getString("state"));haDeviceList.add(haDevice);}if (temp.getString("entity_id").startsWith("light")) {jsonArrayCover.add(jsonArray.getJSONObject(i));haDevice = new HashMap<>();haDevice.put("deviceId", temp.getString("entity_id"));haDevice.put("friendly_name", temp.getJSONObject("attributes").getString("friendly_name"));haDevice.put("type", temp.getString("light"));haDevice.put("state", temp.getString("state"));haDevice.put("deviceType", "light");redisUtil.set("ha_state_" + temp.getString("entity_id"), temp.getString("state"));haDeviceList.add(haDevice);}}return haDeviceList;}/*** 控制控制** @return*/public Integer deviceControl(String deviceType, String entityId, String state, String postion) {// header填充RequestCallback requestCallback = getRequestCallback();ResponseExtractor<ResponseEntity<String>> responseExtractor = restTemplate.responseEntityExtractor(String.class);MultiValueMap<String, String> paramMap = new LinkedMultiValueMap<>();String url = "";// 执行execute(),发送请求switch (deviceType) {case "cover":paramMap.add("entity_id", "cover." + entityId);if (state.equalsIgnoreCase("open") || state.equalsIgnoreCase("close") || state.equalsIgnoreCase("pause")) {url = "/api/services/cover/" + state + "_cover";} else if (state.equalsIgnoreCase("position")) {paramMap.add("position", postion);url = "/api/services/cover/set_cover_position";}break;case "switch":paramMap.add("entity_id", "switch." + entityId);if (state.equalsIgnoreCase("open")) {url = "/api/services/" + deviceType + "/turn_on";} else if (state.equalsIgnoreCase("close")) {url = "/api/services/" + deviceType + "/turn_off";}break;case "light":paramMap.add("entity_id", "light." + entityId);if (state.equalsIgnoreCase("open")) {url = "/api/services/" + deviceType + "/turn_on";} else if (state.equalsIgnoreCase("close")) {url = "/api/services/" + deviceType + "/turn_off";}break;case "fan":paramMap.add("entity_id", "switch." + entityId);if (state.equalsIgnoreCase("open")) {url = "/api/services/" + deviceType + "/turn_on";} else if (state.equalsIgnoreCase("close")) {url = "/api/services/" + deviceType + "/turn_off";}break;default:}ResponseEntity<String> response = restTemplate.execute(hassUrl + url, HttpMethod.POST, requestCallback, responseExtractor, paramMap);return response.getStatusCodeValue();}/*** 定义hedader** @return*/private RequestCallback getRequestCallback() {LinkedMultiValueMap<String, String> headers = new LinkedMultiValueMap<>();headers.add("Authorization", "Bearer " + hassLongToken);headers.add("Content-Type", "application/json");// 获取单例RestTemplateHttpEntity request = new HttpEntity(headers);return restTemplate.httpEntityCallback(request, JSONArray.class);}
}

天猫精灵对接智能设备相关推荐

  1. 天猫精灵对接AliOS ESP32 设备

    天猫精灵对接AliOS ESP32 设备 1. 介绍 IoT物联网变得越来越火热, 智能家居已经走入家庭. 智能设备,如灯, 开关, 空调, 温湿度传感器, 风扇, 扫地机器人都可以通过智能音箱来控制 ...

  2. (8)香橙派+apache2与php+天猫精灵=自建平台语音支持--天猫精灵对接3

    导航链接 (1)香橙派+apache2与php+天猫精灵=自建平台语音支持--前言 (2)香橙派+apache2与php+天猫精灵=自建平台语音支持--香橙派操作系统安装 (3)香橙派+apache2 ...

  3. (6)香橙派+apache2与php+天猫精灵=自建平台语音支持--天猫精灵对接1

    导航链接 (1)香橙派+apache2与php+天猫精灵=自建平台语音支持--前言 (2)香橙派+apache2与php+天猫精灵=自建平台语音支持--香橙派操作系统安装 (3)香橙派+apache2 ...

  4. (11)香橙派+apache2与php+天猫精灵=自建平台语音支持--天猫精灵对接6

    导航链接 (1)香橙派+apache2与php+天猫精灵=自建平台语音支持--前言 (2)香橙派+apache2与php+天猫精灵=自建平台语音支持--香橙派操作系统安装 (3)香橙派+apache2 ...

  5. 天猫精灵对接php源码,天猫精灵对接3 (具体代码实现)

    1.有什么协议问题,请先看对接文档 2.基础流程请看上一篇文章,已经讲得比较详细了. 3.代码写得渣,有什么可以优化的地方麻烦提一下,喷我也没啥用. 运行(调试)流程: 本机测试(内网模拟授权流程): ...

  6. 天猫精灵智能设备对接(8) 开发者网关地址

    洋洋洒洒六七千字已经搭进去了,终于把服务器篇写的差不多了,当然小狂不是专业的写手,有些东西写的凑合看吧,只是说明过程,并不修饰言辞,看的舒服就点个赞,不舒服就当学东西了吧.这篇文章我们将完成天猫精灵服 ...

  7. 2018个人年度总结:我是如何从嵌入式开发到服务器开发对接天猫精灵、小爱智能音箱服务器!懵懂 | 奋斗 | 进阶 | 信心

    文章目录 一.个人总结? 二.步入职场那些事. 2.1 大学项目引起兴趣. 2.2 第一次面试. 二.职业发展的奠基石------ 机智云. 三.嵌入式开发.移动开发.服务器开发. 3.1.嵌入式开发 ...

  8. esp8266对接天猫精灵(8)开发者网关地址

    洋洋洒洒六七千字已经搭进去了,终于把服务器篇写的差不多了,当然小狂不是专业的写手,有些东西写的凑合看吧,只是说明过程,并不修饰言辞,看的舒服就点个赞,不舒服就当学东西了吧.这篇文章我们将完成天猫精灵服 ...

  9. php对接AliGenie天猫精灵服务器控制智能硬件esp8266③ 渗入熟悉AliGenie 对接协议,揭开第三方云平台是如何让天猫精灵是发送消息到私有服务器的!

    本系列博客学习由非官方人员 半颗心脏 潜心所力所写,仅仅做个人技术交流分享,不做任何商业用途.如有不对之处,请留言,本人及时更改. 1. php对接AliGenie天猫精灵服务器控制智能硬件esp82 ...

最新文章

  1. [转] Leaving patterns practices
  2. 参与组织社区活动总结
  3. k8s基础概念:pause容器和pod控制器类型
  4. HashSet集合存储数据的结构(哈希表)
  5. 食饵捕食者模matlab,几类食饵-捕食者模型的定性分析和数值模拟
  6. Unity 编辑器内建图标获得
  7. html插入精灵,帮助插入超链接到CSS精灵代码..Java? HTML?
  8. 使用Movavi Video Editor如何做局部的影片放大特效
  9. 【CF Round #534 Div2】B:Game with string(水题,积累思路)
  10. 基于RV1126平台imx291分析 --- rkcif_mipi注册
  11. C/C++:构建你自己的插件框架(1)
  12. 【渝粤题库】陕西师范大学164210 冲突与沟通管理 作业 (专升本)
  13. python推箱子代码详细讲解_python实现推箱子游戏
  14. 面试问题 你如何评价你上一家公司,你觉的上一家公司怎么评价你
  15. 读《大秦帝国》第三部
  16. 国际贸易术语解释通则(DDP 完税后交货(……指定目的港))
  17. 单片机diy作品鉴赏,初学者进来膜拜
  18. java卡牌游戏详解
  19. Java中Properties类的使用
  20. 使用PlayCanvas制作一个简单的小游戏(一)

热门文章

  1. 秋招干货|给面试官满分的自我介绍
  2. Android Market api
  3. Jodd HTTP的使用
  4. Unity Shader - ddx/ddy偏导函数测试,实现:锐化、高度图、Flat shading应用、高度生成法线
  5. java中去字符串中的(全角)空格
  6. java jdk 8u101_JDK1.8安装
  7. js中对象合并的4种方式,数组合并的4种方法
  8. 相关向量机(RVM)
  9. Dell H310配置no-raid直通模式
  10. 云教室桌面虚拟化环境搭建——flexVDI Dashboard 3.0 云桌面管理系统的使用