获取设备相关属性, 生成相应的米家插件代码
// ==UserScript==
// @name 米家插件相关代码生成
// @namespace http://tampermonkey.net/
// @version 0.4
// @description 获取设备相关属性, 生成相应的米家插件代码
// @author kkopite
// @match https://iot.mi.com/fe-op/productCenter/config/function/detail*
// @require https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js
// @grant none
// ==/UserScript==
(function() {
"use strict";
function es(sel) {
return document.querySelectorAll(sel);
}
function copy(copyTxt) {
// input不会保留换行符
var createInput = document.createElement("textarea");
createInput.value = copyTxt;
document.body.appendChild(createInput);
createInput.select(); //选择对象
document.execCommand("Copy"); //执行浏览器复制命令
createInput.className = "createInput";
createInput.style.display = "none";
alert("复制成功,可以粘贴了!");
console.log(copyTxt);
}
function getSiid() {
const search = location.search.substring(1);
let siid = "";
search.split("&").forEach(str => {
const arr = str.split("=");
if (arr[0] === "siid") {
siid = arr[1];
}
});
return siid;
}
// 获取相关属性
/**
* @returns {Array<{piid: number, name: string, desc: string, propStr: string, type: string, value: string | number}>}
*/
function getProperty() {
const ps = document.querySelector(".funcDefineDetail-item").querySelectorAll("tbody>tr");
const res = [];
ps.forEach(tr => {
const vals = [...tr.cells].map(item => item.innerText);
const name = _.camelCase(vals[1])
res.push({
piid: vals[0],
name,
desc: vals[2],
type: vals[4],
value: getDefaultValue(vals[4]),
propStr: `command.${name}.prop`
});
});
return res;
}
// 生成所需的代码
function generateProperty() {
const arr = getProperty();
const siid = getSiid();
const code = arr
.map(item => {
return `${item.name}: {
did,
prop: 'props.${siid}.${item.piid}',
siid: ${siid},
piid: ${item.piid}
}`;
})
.join(",\n");
copy(code);
}
function getDefaultValue(type) {
switch (type) {
case "bool":
return false;
case "float":
case "uint8":
case "uint16":
return 0;
default:
return "''";
}
}
// 生成react组件中 关于这些属性的声明, 获取, 订阅
function generateReactCode() {
const arr = getProperty()
const code =
`state = {
${arr.map(({name, value, desc}) => {
return `
// ${desc}
${name}: ${value}`
}).join(',\n')}
}
initData () {
getPropertiesValue([
${arr.map(({name}) => 'command.' + name).join(',\n')}
]).then(res => {
${arr.map(({name, value}, idx) => {
return `const ${name} = res[${idx}].value`
}).join('\n')}
this.setState({
${arr.map(({name}) => name).join(',\n')}
})
})
}
register () {
this.subcription = null
this.listener = addListener(
(device, messages) => {
console.log('Device received', messages)
${arr.map(({name, propStr}, idx) => {
const res = `if (messages.has(${propStr})) {
const ${name} = messages.get(${propStr})[0]
this.setState({
${name}
})
}`
if (idx === 0) return res
return ' else ' + res
}).join('')}
})
subscribeMessages(
${arr.map(({propStr}) => propStr).join(',\n')}
).then(subcription => {
console.log('subcription success')
this.subcription = subcription
}).catch(e => {
console.log('subscription failed', e)
})
}
unRegister () {
this.subcription && this.subcription.remove()
this.listener && this.listener.remove()
}
`
copy(code)
}
function addBtn(name, func) {
const btn = document.createElement("button");
btn.innerText = name;
btn.addEventListener("click", func);
btnContainer.appendChild(btn);
}
let btnContainer = null;
function init() {
btnContainer = document.createElement("div");
btnContainer.style.position = "fixed";
btnContainer.style.top = "64px";
btnContainer.style.right = 0;
btnContainer.style.padding = "10px";
document.body.append(btnContainer);
addBtn("获取属性代码", generateProperty);
addBtn("生成属性订阅,获取代码", generateReactCode);
}
init();
})();