add relay charts and optimize relay settings

This commit is contained in:
2026-09-10 01:13:42 +03:30
parent ece4b17edf
commit 91ad61bdee
67 changed files with 4879 additions and 1491 deletions

View File

@@ -1,6 +1,8 @@
using Microsoft.AspNetCore.Mvc;
using GreenHome.Application;
using Microsoft.AspNetCore.Http;
using System.Text;
using System.Text.RegularExpressions;
namespace GreenHome.Api.Controllers;
@@ -31,6 +33,7 @@ public class TelemetryController : ControllerBase
public async Task<ActionResult<string>> Create([FromQuery] TelemetryDto telementry, [FromQuery] string? lastUpdateDate, CancellationToken cancellationToken)
{
telementry.TimestampUtc = DateTime.UtcNow;
telementry.RelayStates = ParseRelayStates(Request.Query);
var id = await telemetryService.AddAsync(telementry, cancellationToken);
var parts = new List<string> { $"ID:{id}" };
@@ -92,6 +95,32 @@ public class TelemetryController : ControllerBase
}));
}
/// <summary>
/// Collect relay states from query params r1, r2, ... (missing relay = off/0).
/// </summary>
private static string? ParseRelayStates(IQueryCollection query)
{
var entries = new List<(int Index, string Value)>();
foreach (var key in query.Keys)
{
var match = Regex.Match(key, @"^r(\d+)$", RegexOptions.IgnoreCase);
if (!match.Success || !int.TryParse(match.Groups[1].Value, out var index) || index <= 0)
continue;
entries.Add((index, query[key].ToString() == "1" ? "1" : "0"));
}
if (entries.Count == 0)
return null;
var states = new string[entries.Max(e => e.Index)];
Array.Fill(states, "0");
foreach (var entry in entries)
states[entry.Index - 1] = entry.Value;
return string.Join(",", states);
}
/// <summary>
/// Parse date string in format: yyyy/MM/dd-HH:mm
/// </summary>

View File

@@ -1,4 +1,4 @@
import{e as br,g as Pt,j as W,r as Te,h as wr,L as Sr,E as Er,B as Cr,R as Ir,k as Tr,t as en}from"./index-DukGkLqQ.js";/**
import{e as br,g as Pt,j as W,r as Te,h as wr,L as Sr,E as Er,B as Cr,R as Ir,k as Tr,t as en}from"./index-BNRf8j5s.js";/**
* @license lucide-react v0.553.0 - ISC
*
* This source code is licensed under the ISC license.

View File

@@ -1 +1 @@
import{j as s,T as g,P as N,S as b,W as v,r,i as m,f as T,a as W,b as E,Q as S,c as w,L as C,E as L,B as M,R as H,M as P,d as k}from"./index-DukGkLqQ.js";function O({weatherData:e,selectedDate:a}){return s.jsx("div",{className:"space-y-6",children:s.jsxs("div",{className:"bg-white rounded-lg border border-gray-200 overflow-hidden",children:[s.jsx("div",{className:"bg-blue-600 p-5",children:s.jsxs("div",{className:"text-center text-white",children:[s.jsx("p",{className:"text-sm opacity-90 mb-1",children:"📅 وضعیت آب و هوای روز"}),s.jsx("p",{className:"text-xl font-bold",children:a})]})}),s.jsxs("div",{className:"p-4 grid grid-cols-2 gap-3",children:[s.jsx(g,{weatherData:e,isToday:!1}),s.jsx(N,{weatherData:e}),s.jsx(b,{weatherData:e}),s.jsx(v,{weatherData:e})]})]})})}function R({selectedDate:e}){const[a,t]=r.useState(null),[h,o]=r.useState(!1),[c,n]=r.useState(null),[f,d]=r.useState(null),[j,i]=r.useState("در حال دریافت..."),x=r.useCallback(async()=>{if(!a){o(!0),n(null);try{const l=m(e),[p,y]=await Promise.all([l?T():W(e),E(S,w)]);t(p),i(y)}catch(l){console.error("Error loading weather:",l),n("خطا در دریافت اطلاعات آب و هوا. لطفاً دوباره تلاش کنید."),i("کهک قم، ایران")}finally{o(!1)}}},[e,a]);if(r.useEffect(()=>{t(null),n(null),d(null),i("در حال دریافت...")},[e]),h)return s.jsx(C,{message:"در حال دریافت اطلاعات آب و هوا...",fullScreen:!1});if(c)return s.jsx(L,{message:c,action:s.jsx(M,{onClick:()=>{t(null),x()},variant:"primary",icon:H,children:"تلاش مجدد"})});if(!a)return x(),null;const u=m(e);return s.jsxs("div",{className:"space-y-6",children:[s.jsxs("div",{className:"flex items-center justify-between",children:[s.jsxs("div",{className:"flex items-center gap-2 text-gray-600",children:[s.jsx(P,{className:"w-5 h-5 text-sky-500"}),s.jsx("span",{className:"font-medium",children:j})]}),s.jsx("span",{className:"text-xs text-gray-400",children:u?"پیش‌بینی هواشناسی برای مدیریت گلخانه":"وضعیت آب و هوای روز انتخاب شده"})]}),u?s.jsx(k,{weatherData:a,expandedDayIndex:f,onDayToggle:d}):s.jsx(O,{weatherData:a,selectedDate:e})]})}export{R as WeatherTab};
import{j as s,T as g,P as N,S as b,W as v,r,i as m,f as T,a as W,b as E,Q as S,c as w,L as C,E as L,B as M,R as H,M as P,d as k}from"./index-BNRf8j5s.js";function O({weatherData:e,selectedDate:a}){return s.jsx("div",{className:"space-y-6",children:s.jsxs("div",{className:"bg-white rounded-lg border border-gray-200 overflow-hidden",children:[s.jsx("div",{className:"bg-blue-600 p-5",children:s.jsxs("div",{className:"text-center text-white",children:[s.jsx("p",{className:"text-sm opacity-90 mb-1",children:"📅 وضعیت آب و هوای روز"}),s.jsx("p",{className:"text-xl font-bold",children:a})]})}),s.jsxs("div",{className:"p-4 grid grid-cols-2 gap-3",children:[s.jsx(g,{weatherData:e,isToday:!1}),s.jsx(N,{weatherData:e}),s.jsx(b,{weatherData:e}),s.jsx(v,{weatherData:e})]})]})})}function R({selectedDate:e}){const[a,t]=r.useState(null),[h,o]=r.useState(!1),[c,n]=r.useState(null),[f,d]=r.useState(null),[j,i]=r.useState("در حال دریافت..."),x=r.useCallback(async()=>{if(!a){o(!0),n(null);try{const l=m(e),[p,y]=await Promise.all([l?T():W(e),E(S,w)]);t(p),i(y)}catch(l){console.error("Error loading weather:",l),n("خطا در دریافت اطلاعات آب و هوا. لطفاً دوباره تلاش کنید."),i("کهک قم، ایران")}finally{o(!1)}}},[e,a]);if(r.useEffect(()=>{t(null),n(null),d(null),i("در حال دریافت...")},[e]),h)return s.jsx(C,{message:"در حال دریافت اطلاعات آب و هوا...",fullScreen:!1});if(c)return s.jsx(L,{message:c,action:s.jsx(M,{onClick:()=>{t(null),x()},variant:"primary",icon:H,children:"تلاش مجدد"})});if(!a)return x(),null;const u=m(e);return s.jsxs("div",{className:"space-y-6",children:[s.jsxs("div",{className:"flex items-center justify-between",children:[s.jsxs("div",{className:"flex items-center gap-2 text-gray-600",children:[s.jsx(P,{className:"w-5 h-5 text-sky-500"}),s.jsx("span",{className:"font-medium",children:j})]}),s.jsx("span",{className:"text-xs text-gray-400",children:u?"پیش‌بینی هواشناسی برای مدیریت گلخانه":"وضعیت آب و هوای روز انتخاب شده"})]}),u?s.jsx(k,{weatherData:a,expandedDayIndex:f,onDayToggle:d}):s.jsx(O,{weatherData:a,selectedDate:e})]})}export{R as WeatherTab};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -12,8 +12,8 @@
<link rel="apple-touch-icon" href="/icon-512.png" />
<link rel="stylesheet" href="/fonts/vazirmatn/style.css" />
<title>GreenHome</title>
<script type="module" crossorigin src="/assets/index-DukGkLqQ.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-8ZWM35nx.css">
<script type="module" crossorigin src="/assets/index-BNRf8j5s.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-DiVRKiu2.css">
</head>
<body>
<div id="root"></div>