23/09/2026
Je cherche une ou plusieurs personnes volontaires pour tester un widget de la station météo Trets en Paca sur leur téléphone Android. mise à jours tous les 20 minutes
1 telecharger sur google store https://play.google.com/store/apps/details?id=com.websitewidget.app
2 Écran d'accueil → appui long → Widget → ajouter WebsiteWidget
Indiquer ton tableau de bord personnel comme URL :
⏩️ https://skyvex.org/widget/bxb7he ◀️ en direct de la station
Sur apple iphone un peut plus de travaille mais fonctionnel
Voici comment faire :
telecharger Scriptable installer depuis l'App Store
Ouvrir l'app et créer un nouveau script
Copier le code ci-dessous et le coller
Enregistre le script (p. ex. Météo )
Écran d'accueil → Ajouter un widget → Scriptable → Météo
// ==================================
// Skyvex Weather – Scriptable Widget
// ==================================
// Zeigt Temperatur, Wind und Niederschlag deiner Station.
// Widget auf den Homescreen legen → Scriptable → dieses Script wählen
const STATION_ID = "bxb7he";
const BASE_URL = "https://skyvex.org";
const API_URL = `${BASE_URL}/api/v1/station/${STATION_ID}/current`;
const CONDITION_ICONS = {
sunny: { symbol: "sun.max.fill", color: " " },
partly: { symbol: "cloud.sun.fill", color: " " },
cloudy: { symbol: "cloud.fill", color: " " },
overcast: { symbol: "smoke.fill", color: " " },
drizzle: { symbol: "cloud.drizzle.fill", color: " " },
rain: { symbol: "cloud.rain.fill", color: " " },
night: { symbol: "moon.stars.fill", color: " " },
snow: { symbol: "cloud.snow.fill", color: " " },
thunderstorm: { symbol: "cloud.bolt.rain.fill", color: " " },
// Ohne Strahlungsmesser: Symbol nach Sonnenstand, aber ohne Wort - die
// Beschriftung dazu ist leer (siehe App\Support\Wetterlage).
day_unknown: { symbol: "sun.max.fill", color: " " },
night_unknown: { symbol: "moon.stars.fill", color: " " },
unknown: { symbol: "circle.dashed", color: " " },
};
// Dynamic background gradients based on condition
const CONDITION_BG = {
sunny: { light: [" ", " "], dark: [" #431407", " "] },
partly: { light: [" ", " "], dark: [" ", " "] },
cloudy: { light: [" ", " "], dark: [" ", " #334155"] },
overcast: { light: [" ", " "], dark: [" ", " "] },
drizzle: { light: [" ", " "], dark: [" ", " "] },
rain: { light: [" ", " "], dark: [" ", " #172554"] },
night: { light: [" ", " "], dark: [" #020617", " "] },
snow: { light: [" ", " "], dark: [" ", " "] },
thunderstorm: { light: [" ", " "], dark: [" ", " "] },
day_unknown: { light: [" ", " "], dark: [" #431407", " "] },
night_unknown: { light: [" ", " "], dark: [" #020617", " "] },
unknown: { light: [" ", " "], dark: [" ", " #334155"] },
};
async function loadData() {
const req = new Request(API_URL);
req.headers = { Accept: "application/json" };
return await req.loadJSON();
}
// Kurzbeschriftungen der Wetterlage - eine Zeile im Widget traegt keine
// 18 Zeichen. Lagen ohne Strahlungsmesser bleiben bewusst leer.
const CONDITION_LABELS = {"sunny":"Ensoleillé","partly":"Partiellement nuageux","cloudy":"Nuageux","overcast":"Couvert","drizzle":"Bruine","rain":"Pluie","snow":"Neige","thunderstorm":"Orage","night":"Nuit","day_unknown":"","night_unknown":"","unknown":""};
function conditionLabel(c) {
return CONDITION_LABELS[c] || "";
}
function createSymbol(name, size) {
const s = SFSymbol.named(name);
s.applyFont(Font.systemFont(size));
return s.image;
}
async function createWidget() {
const data = await loadData();
const w = new ListWidget();
const isDark = Device.isUsingDarkAppearance();
const mode = isDark ? "dark" : "light";
const isMedium = config.widgetFamily !== "small";
// Set background based on weather condition
const bg = CONDITION_BG[data.condition] || CONDITION_BG.cloudy;
const grad = new LinearGradient();
grad.colors = bg[mode].map(c => new Color(c));
grad.locations = [0, 1];
w.backgroundGradient = grad;
w.setPadding(14, 14, 14, 14);
if (data.error || data.is_stale) {
const errBg = CONDITION_BG.cloudy;
const errGrad = new LinearGradient();
errGrad.colors = errBg[mode].map(c => new Color(c));
errGrad.locations = [0, 1];
w.backgroundGradient = errGrad;
const t = w.addText(data.error || "Aucune donnée actuelle");
t.font = Font.mediumSystemFont(14);
t.textColor = Color.red();
return w;
}
// Header: Location + Condition Icon
const header = w.addStack();
header.layoutHorizontally();
header.centerAlignContent();
const cond = CONDITION_ICONS[data.condition] || CONDITION_ICONS.cloudy;
const ci = header.addImage(createSymbol(cond.symbol, 18));
ci.imageSize = new Size(20, 20);
ci.tintColor = new Color(cond.color);
header.addSpacer(6);
const loc = header.addText(data.location_name || STATION_ID);
loc.font = Font.semiboldSystemFont(13);
loc.textColor = isDark ? Color.white() : new Color(" ");
loc.lineLimit = 1;
w.addSpacer(6);
// Temperature + Condition (side by side, temp takes priority)
const ts = w.addStack();
ts.layoutHorizontally();
ts.bottomAlignContent();
const tv = data.temperature_c != null
? data.temperature_c.toFixed(1) : "--";
// °C ausgeschrieben: das Skript liest ausschliesslich temperature_c, ist also
// immer metrisch - anders als das Dashboard, das den Anzeigeeinheiten der
// Station folgt. Ein blosses "°" liesse offen, welche der beiden Skalen hier
// gilt.
const tt = ts.addText(`${tv}°C`);
tt.font = Font.boldSystemFont(32);
tt.lineLimit = 1;
tt.minimumScaleFactor = 0.7;
tt.textColor = isDark ? Color.white() : new Color(" ");
ts.addSpacer(null);
const cl = ts.addText(conditionLabel(data.condition));
cl.font = Font.mediumSystemFont(12);
cl.textColor = isDark ? new Color(" ") : new Color(" #475569");
cl.lineLimit = 1;
cl.minimumScaleFactor = 0.8;
w.addSpacer(6);
// Wind + Rain
const d = w.addStack();
d.layoutHorizontally();
d.spacing = 16;
const ws = d.addStack();
ws.layoutHorizontally();
ws.centerAlignContent();
const wi = ws.addImage(createSymbol("wind", 12));
wi.imageSize = new Size(14, 14);
wi.tintColor = isDark ? new Color(" ") : new Color(" ");
ws.addSpacer(4);
const wk = data.wind_speed_kmh != null
? Math.round(data.wind_speed_kmh) : "--";
const wt = ws.addText(`${wk} km/h ${data.wind_dir_label || ""}`);
wt.font = Font.mediumSystemFont(12);
wt.textColor = isDark ? new Color(" ") : new Color(" #334155");
const rs = d.addStack();
rs.layoutHorizontally();
rs.centerAlignContent();
const ri = rs.addImage(createSymbol("drop.fill", 12));
ri.imageSize = new Size(14, 14);
ri.tintColor = isDark ? new Color(" ") : new Color(" ");
rs.addSpacer(4);
const rv = data.daily_rain_mm != null
? Math.round(data.daily_rain_mm * 10) / 10 : "0";
const rt = rs.addText(`${rv} mm`);
rt.font = Font.mediumSystemFont(12);
rt.textColor = isDark ? new Color(" ") : new Color(" #334155");
// Humidity + Pressure (medium/large only)
if (isMedium) {
w.addSpacer(4);
const d2 = w.addStack();
d2.layoutHorizontally();
d2.spacing = 16;
const hs = d2.addStack();
hs.layoutHorizontally();
hs.centerAlignContent();
const hi = hs.addImage(createSymbol("humidity.fill", 12));
hi.imageSize = new Size(14, 14);
hi.tintColor = isDark ? new Color(" ") : new Color(" ");
hs.addSpacer(4);
const hv = data.humidity != null ? Math.round(data.humidity) : "--";
const ht2 = hs.addText(`${hv} %`);
ht2.font = Font.mediumSystemFont(12);
ht2.textColor = isDark ? new Color(" ") : new Color(" #334155");
const ps = d2.addStack();
ps.layoutHorizontally();
ps.centerAlignContent();
const pi = ps.addImage(createSymbol("gauge.medium", 12));
pi.imageSize = new Size(14, 14);
pi.tintColor = isDark ? new Color(" ") : new Color(" ");
ps.addSpacer(4);
const pv = data.pressure_hpa != null ? Math.round(data.pressure_hpa) : "--";
const pt = ps.addText(`${pv} hPa`);
pt.font = Font.mediumSystemFont(12);
pt.textColor = isDark ? new Color(" ") : new Color(" #334155");
}
w.addSpacer(4);
// Timestamp
const ft = w.addText(`Stand: ${data.observed_at_local}`);
ft.font = Font.regularSystemFont(9);
ft.textColor = isDark ? new Color(" ") : new Color(" ");
w.url = `${BASE_URL}/widget/${STATION_ID}`;
return w;
}
const widget = await createWidget();
if (config.runsInWidget) {
Script.setWidget(widget);
} else {
await widget.presentMedium();
}
Script.complete();
en attente de réponse de votre part ci cela fonctionne merci