From f88501078f892cdbbc80330940387eeb9b14dd74 Mon Sep 17 00:00:00 2001 From: rasta5man Date: Thu, 7 Aug 2025 16:13:43 +0200 Subject: [PATCH] Display bus departures generated by script; get weather temperature from cloud --- src/App.tsx | 127 ++++++++++++++++++++++++++++++++++++------------- src/types.d.ts | 59 +++++++++++++---------- 2 files changed, 126 insertions(+), 60 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index a4b508a..bb3ff48 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -5,11 +5,21 @@ import "./App.css"; import { TChildren, TRssItem, TRssRawItem, TDepartures } from "./types"; import { convertXML } from "simple-xml-to-json"; +const MAIN_URL = "http://10.0.0.30:3000/"; const MAIN_HEADER_FONT_SIZE = 50; const DATA_FONT_SIZE = 42; -const TEMPERATURE_URL = "http://10.0.0.106:3000/gettemperature"; -const DEPARTURES_URL = "http://10.0.0.106:3000/getdepartures"; +const TEMPERATURE_URL = `${MAIN_URL}gettemperature`; +const DEPARTURES_URL = `${MAIN_URL}getdepartures`; + +const GET_RSSFEED_FROM_FILE_URL = `${MAIN_URL}get_rssfeed_data`; +const SET_RSSFEED_TO_FILE_URL = `${MAIN_URL}set_rssfeed_data`; const SOKOLOV_RSS_URL = "https://www.sokolov.cz/rss/"; +const NUMBER_OF_RSSFEED_REQUESTS_BEFORE_LOADING_IT_FROM_FILE = 9; +let rssfeedRequestSuccessful = false; +let getRssFeedAttempts = 0; +const REPEAT_NORMAL_RSSFEED_REQUEST_TIME = 2; // After how long should I get RSS feed? In hours. +const REPEAT_RSS_REQUEST_TIME_AFTER_FAIL = 30 * 1000; //20 seconds + const DAYS_OF_WEEK = [ "Neděle", "Pondělí", @@ -19,8 +29,10 @@ const DAYS_OF_WEEK = [ "Pátek", "Sobota", ]; + const INACTIVITY_LIMIT = 300000; const OPTIONS = { hour12: false }; + // colors in sokolov website const LOGO_COLOR = "#82c55b"; // green const FONT_COLOR = "#00367b"; // blue @@ -43,10 +55,10 @@ function onInactive(ms: number, cb: () => void) { window.onkeydown = window.onkeyup = window.onfocus = - function () { - clearTimeout(wait); - wait = setTimeout(cb, ms); - }; + function() { + clearTimeout(wait); + wait = setTimeout(cb, ms); + }; } function App() { @@ -57,7 +69,7 @@ function App() { var [chosenArticle, setChosenArticle] = useState({ clicked: false, url: "" }); var [feedData, setFeedData] = useState([ { - title: "Chyba stažení dat, kontaktujte prosím administrátora", + title: "", description: "", link: "", pubDate: new Date(), @@ -67,7 +79,7 @@ function App() { // check, how long is user inactive, if reading an article. If more than 5 minutes, we load default screen function idle() { - onInactive(INACTIVITY_LIMIT, function () { + onInactive(INACTIVITY_LIMIT, function() { window.onmousemove = window.onmousedown = window.onmousemove = @@ -78,7 +90,7 @@ function App() { window.onkeydown = window.onkeyup = window.onfocus = - null; + null; setChosenArticle({ clicked: false, url: "" }); }); } @@ -114,14 +126,14 @@ function App() { "Access-Control-Allow-Origin": "*", }, }) - .then((response) => { + .then(response => { let t = parseFloat(response.data); //console.log(t); if (isNaN(t)) return; setTemperature(t); }) - .catch((error) => { + .catch(error => { console.log(error); }); } @@ -132,11 +144,11 @@ function App() { "Access-Control-Allow-Origin": "*", }, }) - .then((response) => { + .then(response => { const departures: TDepartures = response.data; setDepartures(departures); }) - .catch((error) => { + .catch(error => { console.log(error); }); } @@ -156,7 +168,7 @@ function App() { setDayOfWeek(DAYS_OF_WEEK[date.getDay()]); msToMidnight = milisecondsToMidnight(); - console.log("setDay called, ms to midnight", msToMidnight); + //console.log("setDay called, ms to midnight", msToMidnight); updateDayOfWeek = setInterval(getDay, msToMidnight); } @@ -177,13 +189,49 @@ function App() { }; }, []); + function getOrSetRssFeedWithFile(rssFeedData: TRssItem[]) { + if (rssFeedData.length === 0) { + axios(GET_RSSFEED_FROM_FILE_URL, { + headers: { + "Access-Control-Allow-Origin": "*", + }, + }) + .then(response => { + let rssFeedData: TRssItem[] = response.data; + console.log("rssfeed data loaded from file: ", rssFeedData); + rssFeedData = rssFeedData.map(item => { + return { ...item, pubDate: new Date(item.pubDate) }; + }) + setFeedData(rssFeedData); + }) + .catch(error => { + console.log(error); + }); + } else { + axios(SET_RSSFEED_TO_FILE_URL, { + method: "post", + headers: { + "Access-Control-Allow-Origin": "*", + }, + data: rssFeedData + }) + .then(response => { + console.log("set rssfeed data response: ", response); + }) + .catch(error => { + console.log(error); + }); + } + } + // rss feed to get articles from sokolov website const getRssFeed = () => { + //console.log('volam get feed'); axios(SOKOLOV_RSS_URL) - .then((response) => { + .then(response => { const myJson = convertXML(response?.data); - console.log("--------", JSON.stringify(myJson)); + //console.log("--------", JSON.stringify(myJson)); let data: TChildren = myJson?.rss?.children[0]?.channel?.children; if (!Array.isArray(data)) return; @@ -204,35 +252,36 @@ function App() { }; }); - console.log(result); + rssfeedRequestSuccessful = true; + //console.log("rssfeed obtained"); + //console.log(result); + //getOrSetRssFeedWithFile(result); setFeedData(result); }) - .catch((e) => console.log(e)); + .catch(_ => { + //getRssFeedAttempts++; + //if (!rssfeedRequestSuccessful && (getRssFeedAttempts > NUMBER_OF_RSSFEED_REQUESTS_BEFORE_LOADING_IT_FROM_FILE && getRssFeedAttempts < NUMBER_OF_RSSFEED_REQUESTS_BEFORE_LOADING_IT_FROM_FILE + 2)) { + // getOrSetRssFeedWithFile([]); + //} + if (!rssfeedRequestSuccessful) { + //console.log('Error obtaining rssfeed, repeating ...'); + setTimeout(getRssFeed, REPEAT_RSS_REQUEST_TIME_AFTER_FAIL); + } + }); }; useEffect(() => { getRssFeed(); - var feed = setInterval(getRssFeed, 6 * 60 * 60 * 1000); //raz za 6 hodin + // ODKOMENTUJ NASLEDUJUCE RIADKY, AK CHCES, ABY SA RSS FEEDY NACITAVALI CASTEJSIE + var feed = setInterval(getRssFeed, REPEAT_NORMAL_RSSFEED_REQUEST_TIME * 60 * 60 * 1000); //raz za REPEAT_NORMAL_RSSFEED_REQUEST_TIME hodin return function cleanup() { clearInterval(feed); }; }, []); const buildFeedView = (): React.JSX.Element[] => { - if ( - feedData[0].title === - "Chyba stažení dat, kontaktujte prosím administrátora" - ) { - return [ - - - {feedData[0].title} - - - {feedData[0].pubDate.toLocaleDateString("cs-Cz")} - - , - ]; + if (feedData[0].title === "") { + return []; } return feedData.map((item, index) => { @@ -259,6 +308,7 @@ function App() { ); }); }; + sokolovFeed = buildFeedView(); return ( @@ -297,7 +347,7 @@ function App() { SMĚR PŘÍJEZD - {departures.map(function (item, i) { + {departures.map(function(item, i) { return ( {item[0]} @@ -357,6 +407,15 @@ const departures = [ ["3", "08:10", "Závodu míru", ["X", "32"]], ]; +// ziskavaju sa requestom na web sokolova +let departures_new = [ + ["6", "07:23", "Sídl.Michal škola", "X2"], + ["3", "07:27", "Sídliště Michal", "X2"], + ["2", "07:31", "Sídliště Michal", "X1"], + ["3", "07:34", "Závodu míru", "X3"], + ["4", "07:34", "Závodu míru", "X1"], +] + // pubDate is date object const dummyData = [ { diff --git a/src/types.d.ts b/src/types.d.ts index fe5324a..146bf09 100644 --- a/src/types.d.ts +++ b/src/types.d.ts @@ -6,43 +6,50 @@ export type TRssItem = { link: string; pubDate: Date; guid: string; - }; - - export type TContent = { content: string }; +}; - export type TRssRawItem = { +export type TContent = { content: string }; + +export type TRssRawItem = { item: { - children: [ - { title: TContent }, - { link: TContent }, - { description: TContent }, - { pubDate: { content: Date } }, - { guid: TContent } - ]; + children: [ + { title: TContent }, + { link: TContent }, + { description: TContent }, + { pubDate: { content: Date } }, + { guid: TContent } + ]; }; - }; - +}; + export type TChildren = { children: [ - |{ - title: TContent; + | { + title: TContent; } - | { - link: TContent; + | { + link: TContent; } - | { - description: TContent; + | { + description: TContent; } - | { - ttl: TContent; + | { + ttl: TContent; } - | { - lastBuildDate: TContent; + | { + lastBuildDate: TContent; } - | { - item: RssRawItem; + | { + item: RssRawItem; } ]; }; -export type TDepartures = array[]; +export type TDepartures = array[]; + +export type TSlackData = { + msg: string + bot_name: string + bot_icon: string + channel: string +};