323 lines
13 KiB
JavaScript
323 lines
13 KiB
JavaScript
/**
|
||
* 基础参数说明:
|
||
* @plugin 全局插件行动 - 策略模式
|
||
* @plugin .default 行动默认数据
|
||
* @plugin _willAppear 在 willAppear 方法之后立即执行
|
||
* @plugin _willDisappear 在 willDisappear 方法之前立即执行
|
||
* @common sendToPlugin keyUp propertyInspectorDidAppear
|
||
* =========================================================================>
|
||
*/
|
||
window.QWEATHER_API_KEY = 'bdd98ec1d87747f3a2e8b1741a5af796';
|
||
window.WEATHERAPI_COM_API_KEY = 'c4aeca457d9e4a36a9982404252804';
|
||
const $local = false,
|
||
$plugin = {
|
||
name: "weather",
|
||
action1: new Action({
|
||
default: {
|
||
inputCity: "", // 输入框
|
||
tempList: "0", //
|
||
cityId: "",
|
||
city: "",
|
||
title: "",
|
||
radio: "0",
|
||
radio2: "0",
|
||
radioUseApi: window.WeatherApiEnum.qweather,
|
||
searchList: [],
|
||
theme: "Modern",
|
||
wdata: { tmp: "20", code: "101" , name: '', img: '', cityName: ''},
|
||
titleParameters: {
|
||
titleColor: "#ffffff",
|
||
},
|
||
count: 0,
|
||
Localization: {}
|
||
},
|
||
/**
|
||
* 1. 和风开发者KEY: 641403ded7f348bf88681308e648bdde
|
||
* 2. 和风官方地理位置KEY: bdd98ec1d87747f3a2e8b1741a5af796
|
||
* 3. 和风官方网页查询数据: https://www.qweather.com/v2/current/condition/s/x-cityId.html
|
||
*/
|
||
async queryLocation(context, device) {
|
||
console.log("queryLocation");
|
||
const data = this.data[context];
|
||
const langMap = {
|
||
'zh_CN': 'zh', 'en': 'en', 'ja': 'ja', 'fr': 'fr',
|
||
'it': 'it', 'ru': 'ru', 'es': 'es', 'pt': 'pt', 'de': 'de'
|
||
};
|
||
const lang = langMap[$lang] || 'en';
|
||
const weatherService = window.WeatherServiceFactory.createWeatherService(data.radioUseApi); // 获取天气服务实例
|
||
|
||
try {
|
||
if (data.inputCity) {
|
||
// console.log("inputCity");
|
||
$websocket.setTitle(context, "Loading");
|
||
const [error, locationList] = await weatherService.queryLocation(data.inputCity, lang);
|
||
|
||
if (error) {
|
||
console.error("queryLocation failed:", error);
|
||
data.searchList = [];
|
||
this.canvasFunc(context, device, "error");
|
||
$websocket.setSettings(context, data);
|
||
} else if (locationList && locationList.length > 0) {
|
||
// **需要根据不同服务商的返回数据结构进行适配**
|
||
// 和风天气返回的是一个包含城市信息的数组 (res.data.location)
|
||
// WeatherAPI.com 返回的也是一个数组 (res.data)
|
||
data.searchList = locationList;
|
||
this.queryWeather(context, device);
|
||
data.count = 0;
|
||
} else {
|
||
data.searchList = [];
|
||
this.canvasFunc(context, device, "404");
|
||
$websocket.setSettings(context, data);
|
||
}
|
||
}
|
||
} catch (e) {
|
||
console.error("queryLocation general error:", e);
|
||
if (++data.count <= 3) {
|
||
this.queryLocation(context, device);
|
||
$websocket.setTitle(context, "Try again");
|
||
return;
|
||
}
|
||
this.canvasFunc(context, device, "error");
|
||
}
|
||
},
|
||
async queryWeather(context, device) {
|
||
const data = this.data[context];
|
||
const weatherService = window.WeatherServiceFactory.createWeatherService(data.radioUseApi); // 获取天气服务实例
|
||
const langMap = {
|
||
'zh_CN': 'zh', 'en': 'en', 'ja': 'ja', 'fr': 'fr',
|
||
'it': 'it', 'ru': 'ru', 'es': 'es', 'pt': 'pt', 'de': 'de'
|
||
};
|
||
const lang = langMap[$lang] || 'en';
|
||
try {
|
||
clearTimeout(data.timer);
|
||
console.log(data,data.cityId, data.searchList)
|
||
// 过滤出用户选择的城市
|
||
data.cityId = (
|
||
data.searchList.filter((item) => item.id === data.cityId)[0] ||
|
||
data.searchList[0]
|
||
)?.id;
|
||
data.city = data.searchList.filter(
|
||
(item) => item.id === data.cityId
|
||
)[0]?.name;
|
||
|
||
if (data.cityId) {
|
||
$websocket.setTitle(context, "Loading");
|
||
const [error, weatherData] = await weatherService.queryWeather(data.cityId, lang);
|
||
|
||
if (error) {
|
||
console.error("queryWeather failed:", error);
|
||
this.canvasFunc(context, device, "error");
|
||
} else if (weatherData) {
|
||
// **需要根据不同服务商的返回数据结构进行适配**
|
||
let tmp, code, img, name, cityName;
|
||
if (weatherService instanceof window.QWeatherService) {
|
||
tmp = weatherData.tmp;
|
||
code = weatherData.code; // 需要查阅和风天气的 icon 对应关系
|
||
} else if (weatherService instanceof window.WeatherApiComService) {
|
||
tmp = weatherData.current.temp_c; // 或 temp_f,根据需求
|
||
code = weatherData.current.condition.code; // 需要查阅 WeatherAPI.com 的 code 对应关系
|
||
img = 'https:' + weatherData.current.condition.icon;
|
||
name = weatherData.current.condition.text;
|
||
cityName = weatherData.location.name;
|
||
}
|
||
|
||
data.wdata = { tmp, code, img, name, cityName};
|
||
data.count = 0;
|
||
data.timer = setTimeout(
|
||
() => this.queryWeather(context, device),
|
||
1000 * 60 * 60 * 1
|
||
);
|
||
$websocket.setSettings(context, data);
|
||
this.canvasFunc(context, device);
|
||
} else {
|
||
this.canvasFunc(context, device, "error");
|
||
}
|
||
}
|
||
} catch (e) {
|
||
console.error("queryWeather general error:", e);
|
||
if (++data.count <= 3) {
|
||
this.queryWeather(context, device);
|
||
$websocket.setTitle(context, "Try again");
|
||
return;
|
||
}
|
||
this.canvasFunc(context, device, "error");
|
||
}
|
||
},
|
||
// 绘制
|
||
async canvasFunc(context, device, status = "success") {
|
||
if (status === "error") {
|
||
$websocket.setImage(
|
||
context,
|
||
this.data[context].isBackgroundHidden
|
||
? "../static/img/tm.png"
|
||
: "../static/img/default.jpg"
|
||
);
|
||
$websocket.setTitle(context, "Timeout");
|
||
return;
|
||
} else if (status === "404") {
|
||
$websocket.setImage(
|
||
context,
|
||
this.data[context].isBackgroundHidden
|
||
? "../static/img/tm.png"
|
||
: "../static/img/default.jpg"
|
||
);
|
||
$websocket.setTitle(context, "Not found");
|
||
return;
|
||
}
|
||
if (!this.data[context].cityId) return;
|
||
|
||
// 主题配置
|
||
const data = this.data[context];
|
||
const { tmp, code, img, name, cityName } = data.wdata;
|
||
// 摄氏度/华氏度
|
||
const unit = data.tempList === "0" ? "℃" : "℉";
|
||
const tmps = data.tempList === "0" ? tmp : tmp * 1.8 + 32;
|
||
|
||
// 设置gif背景
|
||
// if (data.theme == "dynamic") {
|
||
// $websocket.setImage(context,`${dynamicEnum[101]}`, true);
|
||
// $websocket.setTitle(
|
||
// context,
|
||
// data.radio == "0" ? `${Number(tmps).toFixed(1)}${unit}\n${data.city}` : `${Number(tmps).toFixed(1)}${unit}\n${data.title}`
|
||
// );
|
||
// return
|
||
// }
|
||
|
||
// console.log(this.data[context].radioUseApi, window.WeatherApiEnum, data.wdata);
|
||
const image = new Image();
|
||
switch(this.data[context].radioUseApi) {
|
||
case window.WeatherApiEnum.qweather:
|
||
if (data.theme == "Modern")
|
||
image.src = `../static/img/Modern/${code}-fill.svg`;
|
||
if (data.theme == "Luxury")
|
||
image.src = `../static/img/Luxury/${LuxuryEnum[code]}.png`;
|
||
break;
|
||
case window.WeatherApiEnum.weatherapi:
|
||
image.src = img
|
||
break;
|
||
default:
|
||
}
|
||
|
||
|
||
/* 加载完毕后开始 */
|
||
image.onload = async function () {
|
||
let canvas = document.createElement("canvas");
|
||
canvas.width = canvas.height = 512;
|
||
let ctx = canvas.getContext("2d");
|
||
|
||
// 是否隐藏背景 适配 296
|
||
// if (!data.isBackgroundHidden) {
|
||
ctx.fillStyle = "rgba(0,0,0,0)";
|
||
ctx.fillRect(0, 0, 512, 512);
|
||
ctx.save();
|
||
// }
|
||
|
||
if (data.theme == "Modern") ctx.drawImage(this, (512 - 260) / 2, 20, 260, 260);
|
||
if (data.theme == "Luxury") ctx.drawImage(this, -2, -2, 516, 516);
|
||
|
||
// ctx.fillStyle = data.titleParameters.titleColor;
|
||
// ctx.font = `${data.titleParameters.fontStyle == "Regular" ? "" : data.titleParameters.fontStyle} ${data.titleParameters.fontSize + 10}px '${data.titleParameters.fontFamily}'`;
|
||
// ctx.shadowColor = "white";
|
||
// ctx.shadowBlur = 1;
|
||
// ctx.shadowOffsetX = 1;
|
||
// ctx.shadowOffsetY = 1;
|
||
|
||
|
||
// ctx.fillText(`${Number(tmps).toFixed(1)}${unit}`, 14, 29);
|
||
|
||
// if (data.titleParameters.fontUnderline) {
|
||
// let textMetrics = ctx.measureText(`${Number(tmps).toFixed(1)}${unit}`);
|
||
// let underlineHeight = 1;
|
||
// ctx.fillRect(14, 29 + 2, textMetrics.width, underlineHeight);
|
||
// }
|
||
|
||
let weatherName;
|
||
switch(data.radioUseApi) {
|
||
case window.WeatherApiEnum.qweather:
|
||
weatherName = data.radio2 == "0" ? data.Localization[code == 154 ? 153 : code] + "\n" : '';
|
||
data.Localization[code == 154 ? 153 : code] + "\n"
|
||
$websocket.setTitle(
|
||
context,
|
||
weatherName + (data.radio == "0" ? `${Number(tmps).toFixed(1)}${unit}\n${data.city}` : `${Number(tmps).toFixed(1)}${unit}\n${data.title}`)
|
||
);
|
||
break;
|
||
case window.WeatherApiEnum.weatherapi:
|
||
weatherName = data.radio2 == "0" ? name + "\n" : '';
|
||
$websocket.setTitle(
|
||
context,
|
||
weatherName + (data.radio == "0" ? `${Number(tmps).toFixed(1)}${unit}\n${cityName}` : `${Number(tmps).toFixed(1)}${unit}\n${data.title}`),
|
||
);
|
||
break;
|
||
default:
|
||
}
|
||
|
||
// 国际化json文件里面没有154,154与153是一样的夜间多云
|
||
$websocket.setImage(context, canvas.toDataURL("image/png"));
|
||
};
|
||
},
|
||
titleParametersDidChange({ context, payload, device }) {
|
||
this.data[context].titleParameters = payload.titleParameters;
|
||
this.canvasFunc(context, device);
|
||
},
|
||
didReceiveSettings({ context, payload, device }) {
|
||
this.data[context].isBackgroundHidden = payload.settings.isBackgroundHidden;
|
||
this.canvasFunc(context, device);
|
||
},
|
||
async _willAppear({ context, device, payload }) {
|
||
console.log("willAppear", payload);
|
||
|
||
this.data[context].Localization = await new Promise(resolve => {
|
||
const req = new XMLHttpRequest();
|
||
req.open('GET', `../${$lang}.json`);
|
||
req.send();
|
||
req.onreadystatechange = () => {
|
||
if (req.readyState === 4) {
|
||
resolve(JSON.parse(req.responseText).Localization)
|
||
}
|
||
};
|
||
})
|
||
const { radioUseApi } = payload.settings;
|
||
this.data[context].radioUseApi = radioUseApi !== undefined? window.WeatherApiEnum[radioUseApi]: window.WeatherApiEnum.qweather;
|
||
this.queryLocation(context, device);
|
||
},
|
||
_willDisappear({ context}) {
|
||
clearTimeout(this.data[context].timer);
|
||
},
|
||
sendToPlugin({ context, payload, device }) {
|
||
const data = this.data[context];
|
||
const { inputCity, cityId, title, theme, radio, radio2, tempList, radioUseApi } = payload;
|
||
// 切换提供商
|
||
if (radioUseApi !== undefined) {
|
||
data.radioUseApi = radioUseApi;
|
||
this.data[context].radioUseApi = window.WeatherApiEnum[radioUseApi];
|
||
this.data[context].count = 0;
|
||
return this.queryLocation(context, device);
|
||
}
|
||
|
||
// 输入城市
|
||
if (inputCity !== undefined) {
|
||
data.inputCity = inputCity;
|
||
this.data[context].count = 0;
|
||
return this.queryLocation(context, device);
|
||
}
|
||
// 更新天气
|
||
if (cityId !== undefined) {
|
||
data.cityId = cityId;
|
||
this.data[context].count = 0;
|
||
return this.queryWeather(context, device);
|
||
}
|
||
// 更新选项
|
||
if (title !== undefined) data.title = title;
|
||
if (theme !== undefined) data.theme = theme;
|
||
if (radio !== undefined) data.radio = radio;
|
||
if (radio2 !== undefined) data.radio2 = radio2;
|
||
if (tempList !== undefined) data.tempList = tempList;
|
||
this.canvasFunc(context, device);
|
||
},
|
||
keyUp({ context, device }) {
|
||
this.data[context].count = 0;
|
||
this.queryWeather(context, device);
|
||
},
|
||
}),
|
||
};
|