Display bus departures generated by script; get weather temperature from cloud

This commit is contained in:
rasta5man 2025-08-07 16:13:43 +02:00
parent 857ba29540
commit f88501078f
2 changed files with 126 additions and 60 deletions

View file

@ -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,7 +55,7 @@ function onInactive(ms: number, cb: () => void) {
window.onkeydown =
window.onkeyup =
window.onfocus =
function () {
function() {
clearTimeout(wait);
wait = setTimeout(cb, ms);
};
@ -57,7 +69,7 @@ function App() {
var [chosenArticle, setChosenArticle] = useState({ clicked: false, url: "" });
var [feedData, setFeedData] = useState<TRssItem[]>([
{
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 =
@ -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 [
<Box sx={{ padding: 2 }}>
<Typography sx={{ color: LOGO_COLOR }} variant="h6">
{feedData[0].title}
</Typography>
<Typography sx={{ color: FONT_COLOR }} variant="subtitle2">
{feedData[0].pubDate.toLocaleDateString("cs-Cz")}
</Typography>
</Box>,
];
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() {
<td align="left">SMĚR</td>
<td align="center">PŘÍJEZD</td>
</tr>
{departures.map(function (item, i) {
{departures.map(function(item, i) {
return (
<tr key={i} style={{ fontSize: DATA_FONT_SIZE }}>
<td align="center">{item[0]}</td>
@ -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 = [
{

19
src/types.d.ts vendored
View file

@ -6,11 +6,11 @@ export type TRssItem = {
link: string;
pubDate: Date;
guid: string;
};
};
export type TContent = { content: string };
export type TContent = { content: string };
export type TRssRawItem = {
export type TRssRawItem = {
item: {
children: [
{ title: TContent },
@ -20,11 +20,11 @@ export type TRssItem = {
{ guid: TContent }
];
};
};
};
export type TChildren = {
children: [
|{
| {
title: TContent;
}
| {
@ -45,4 +45,11 @@ export type TChildren = {
];
};
export type TDepartures = array<string, string, string, string[]>[];
export type TDepartures = array<number, string, string, string>[];
export type TSlackData = {
msg: string
bot_name: string
bot_icon: string
channel: string
};