Help
RSS
API
Feed
Maltego
Contact
Domain > louth-taincentre.protracs.io
×
More information on this domain is in
AlienVault OTX
Is this malicious?
Yes
No
DNS Resolutions
Date
IP Address
2025-08-11
3.5.69.200
(
ClassC
)
2025-10-18
3.169.173.83
(
ClassC
)
Port 80
HTTP/1.1 301 Moved PermanentlyServer: CloudFrontDate: Sat, 18 Oct 2025 04:13:17 GMTContent-Type: text/htmlContent-Length: 167Connection: keep-aliveLocation: https://louth-taincentre.protracs.io/X-Cache: Redirect from cloudfrontVia: 1.1 7d14d4fc1c149f1d429681a4c414c21a.cloudfront.net (CloudFront)X-Amz-Cf-Pop: HIO52-P4X-Amz-Cf-Id: er_ekHNpCfQrNBO5lw2ovGXIYdzGklVYNXviah6MAbU2iFox7JGfmw html>head>title>301 Moved Permanently/title>/head>body>center>h1>301 Moved Permanently/h1>/center>hr>center>CloudFront/center>/body>/html>
Port 443
HTTP/1.1 200 OKContent-Type: text/htmlContent-Length: 26389Connection: keep-aliveDate: Sat, 18 Oct 2025 04:13:18 GMTLast-Modified: Mon, 11 Aug 2025 12:35:32 GMTETag: 5e2a5b9b0f2727b5d6fbfb14e8e6b15cServer: AmazonS3X-Cache: Miss from cloudfrontVia: 1.1 d71a9f9985c04c59760fd5574a6fe436.cloudfront.net (CloudFront)X-Amz-Cf-Pop: HIO52-P4X-Amz-Cf-Id: 1TI8DEY7W3H4IL1dvOA-xJ_ac0cRA5dzo7FPBQkIGHV3-xzRoWPGTA !DOCTYPE html>html langen>head> meta charsetUTF-8> meta nameviewport contentwidthdevice-width, initial-scale1.0> title>Dundalk Town Hall Water/Gas Flow Usage/title> link relicon hreffavicon.png typeimage/png> script srchttps://cdn.tailwindcss.com>/script> link hrefhttps://fonts.googleapis.com/css2?familyInter:wght@400;500;600;700&displayswap relstylesheet> script srchttps://cdn.jsdelivr.net/npm/chart.js>/script> script srchttps://cdn.jsdelivr.net/npm/chartjs-adapter-date-fns/dist/chartjs-adapter-date-fns.bundle.min.js>/script> link relstylesheet hrefhttps://unpkg.com/leaflet@1.9.4/dist/leaflet.css/> script srchttps://unpkg.com/leaflet@1.9.4/dist/leaflet.js>/script> style> body { font-family: Inter, sans-serif; } .chart-container { position: relative; height: 300px; width: 100%; } #map-container { height: 400px; z-index: 0; } @keyframes pulse-green { 0%, 100% { box-shadow: 0 0 0 0 rgba(34, 197, 94, 0.7); } 50% { box-shadow: 0 0 0 8px rgba(34, 197, 94, 0); } } @keyframes pulse-red { 0%, 100% { box-shadow: 0 0 0 0 rgba(239, 68, 68, 0.7); } 50% { box-shadow: 0 0 0 8px rgba(239, 68, 68, 0); } } @keyframes pulse-yellow { 0%, 100% { box-shadow: 0 0 0 0 rgba(245, 158, 11, 0.7); } 50% { box-shadow: 0 0 0 8px rgba(245, 158, 11, 0); } } .pulse-green { animation: pulse-green 2s infinite; } .pulse-red { animation: pulse-red 2s infinite; } .pulse-yellow { animation: pulse-yellow 2s infinite; } @keyframes flash { 0% { background-color: #fef2f2; } 100% { background-color: #f8fafc; } } .flash-update { animation: flash 1.5s ease-out; } @keyframes slide-in-fade-in { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); } } .animate-on-load { animation: slide-in-fade-in 0.5s ease-out forwards; opacity: 0; } .error-state { background-color: #fee2e2; border: 1px solid #fecaca; } /style>/head>body classbg-slate-100 text-gray-800> div classmax-w-7xl mx-auto p-4 sm:p-6 lg:p-8> header classmb-8> div classflex justify-between items-start> div> h1 classtext-3xl font-bold text-gray-900>Dundalk Town Hall Water/Gas Flow Usage/h1> p classtext-gray-600 mt-1>Real-time monitoring system - New data arrives every 30 minutes/p> /div> div classtext-right> p classtext-sm text-gray-500>Current Time/p> p idcurrent-time classtext-lg font-semibold>/p> /div> /div> div classmt-4 flex items-center justify-between> div classflex items-center space-x-3> div idapi-status-indicator classw-3 h-3 rounded-full bg-gray-400>/div> div classtext-sm text-gray-500>API Status: span idapi-status classfont-mono font-semibold>Initializing.../span>/div> /div> div classflex items-center space-x-4> button onclicktoggleAutoRefresh() idauto-refresh-btn classpx-4 py-2 bg-green-600 text-white rounded-lg hover:bg-green-700 transition-colors text-sm> Auto-refresh: ON /button> /div> /div> !-- Countdown Timer Progress Bar --> div classmt-2 w-full bg-gray-200 rounded-full h-1.5> div idcountdown-bar classbg-blue-600 h-1.5 rounded-full stylewidth: 100%; transition: width 1s linear;>/div> /div> /header> !-- System Summary --> section classmb-8 grid grid-cols-1 md:grid-cols-3 gap-4> div classbg-white p-4 rounded-lg shadow> h3 classtext-sm font-medium text-gray-500>Temperature Difference/h3> p idtemp-difference classtext-2xl font-bold text-gray-900>--°C/p> /div> div classbg-white p-4 rounded-lg shadow> h3 classtext-sm font-medium text-gray-500>Current Power/h3> p idcurrent-power classtext-2xl font-bold text-gray-900>-- kW/p> /div> div classbg-white p-4 rounded-lg shadow> h3 classtext-sm font-medium text-gray-500>Total Cost/h3> p idtotal-cost classtext-2xl font-bold text-gray-900>€--/p> /div> /section> main iddashboard-main-container> div idloading-state classtext-center py-12> div classinline-flex items-center> svg classanimate-spin h-8 w-8 text-blue-600 mr-3 xmlnshttp://www.w3.org/2000/svg fillnone viewBox0 0 24 24> circle classopacity-25 cx12 cy12 r10 strokecurrentColor stroke-width4>/circle> path classopacity-75 fillcurrentColor dM4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z>/path> /svg> p classtext-gray-500>Loading sensor data.../p> /div> /div> div iddata-content classhidden> !-- Latest Readings Section --> section classmb-10 bg-white p-6 rounded-lg shadow-lg animate-on-load> div classflex justify-between items-baseline mb-4> h2 classtext-2xl font-bold text-gray-800>Latest Readings/h2> span idlatest-reading-timestamp classtext-sm text-gray-500>/span> /div> div idmetrics-container classgrid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4>/div> /section> !-- Historical Data Section --> section classbg-white p-6 rounded-lg shadow-lg animate-on-load styleanimation-delay: 100ms;> h2 classtext-2xl font-bold text-gray-800 mb-4>Historical Data (Last 48 Hours)/h2> div classgrid grid-cols-1 lg:grid-cols-2 gap-6> div classbg-slate-50 p-4 rounded-lg> h3 classtext-lg font-semibold text-gray-700 mb-2>Temperature & Flow/h3> div classchart-container> canvas idtemp-flow-chart>/canvas> /div> /div> div classbg-slate-50 p-4 rounded-lg> h3 classtext-lg font-semibold text-gray-700 mb-2>Power & Cost/h3> div classchart-container> canvas idpower-cost-chart>/canvas> /div> /div> /div> /section> /div> /main> !-- Map Section --> footer classmt-12> h2 classtext-2xl font-bold text-gray-800 mb-4>Site Location/h2> div idmap-container classrounded-lg shadow-lg bg-white>/div> /footer> /div> script typemodule> const DEVICE_ID cn3jtVrK; const API_URL https://9i5rqqmos9.execute-api.eu-west-1.amazonaws.com/data; const FETCH_INTERVAL 30000; // 30 seconds window.myCharts {}; let mapInstance null; let autoRefresh true; let countdownInterval; let currentTimeRange 48h; let currentHistoryData ; const metricsContainer document.getElementById(metrics-container); const loadingStateEl document.getElementById(loading-state); const dataContentEl document.getElementById(data-content); const latestReadingTimestampEl document.getElementById(latest-reading-timestamp); const apiStatusEl document.getElementById(api-status); const statusIndicatorEl document.getElementById(api-status-indicator); const countdownBarEl document.getElementById(countdown-bar); // Update current time function updateCurrentTime() { const now new Date(); document.getElementById(current-time).textContent now.toLocaleString(en-IE, { timeZone: Europe/Dublin }); } setInterval(updateCurrentTime, 1000); updateCurrentTime(); function formatCurrency(value) { if (typeof value ! number || isNaN(value)) return €0.00; return new Intl.NumberFormat(en-IE, { style: currency, currency: EUR }).format(value); } function startCountdown() { clearInterval(countdownInterval); let width 100; countdownBarEl.style.width `${width}%`; const step 100 / (FETCH_INTERVAL / 1000); countdownInterval setInterval(() > { width - step; countdownBarEl.style.width `${width}%`; if (width 0) { clearInterval(countdownInterval); } }, 1000); } async function fetchData() { renderMap(); try { apiStatusEl.textContent Fetching...; statusIndicatorEl.className w-3 h-3 rounded-full bg-yellow-400 pulse-yellow; if (!DEVICE_ID) { loadingStateEl.innerHTML `p classtext-lg text-red-600>Configuration needed: Set the DEVICE_ID./p>`; return; } const fullApiUrl `${API_URL}?deviceId${DEVICE_ID}`; const response await fetch(fullApiUrl); if (!response.ok) throw new Error(`API Error: ${response.status}`); const responseData await response.json(); apiStatusEl.textContent `OK (Updated: ${new Date().toLocaleTimeString(en-IE)})`; statusIndicatorEl.className w-3 h-3 rounded-full bg-green-500 pulse-green; loadingStateEl.classList.add(hidden); dataContentEl.classList.remove(hidden); updateUI(responseData); currentHistoryData responseData.history || ; } catch (error) { console.error(Failed to fetch data:, error); apiStatusEl.textContent `Error: ${error.message}`; statusIndicatorEl.className w-3 h-3 rounded-full bg-red-500; loadingStateEl.innerHTML `p classtext-lg text-red-500>Failed to load data: ${error.message}/p>`; } finally { if (autoRefresh) { startCountdown(); } } } function updateUI({ latest, history, totals }) { const timestampOptions { year: numeric, month: 2-digit, day: 2-digit, hour: 2-digit, minute: 2-digit, timeZone: Europe/Dublin }; latestReadingTimestampEl.textContent latest.last_updated_timestamp ? `(as of ${new Date(latest.last_updated_timestamp).toLocaleString(en-IE, timestampOptions)})` : ; // Update summary cards document.getElementById(temp-difference).textContent latest.calculated_tempDifference_C ? `${latest.calculated_tempDifference_C.toFixed(1)}°C` : --°C; document.getElementById(current-power).textContent latest.calculated_power_kW ? `${latest.calculated_power_kW.toFixed(3)} kW` : 0.000 kW; document.getElementById(total-cost).textContent formatCurrency(totals.total_accumulated_cost || 0); const metrics { Forward Temp: { value: latest.forwardTemp_C, unit: °C, icon: svg xmlnshttp://www.w3.org/2000/svg width24 height24 viewBox0 0 24 24 fillnone stroke#dc2626 stroke-width2 stroke-linecapround stroke-linejoinround>path dM14 4v10.54a4 4 0 1 1-4 0V4a2 2 0 0 1 4 0Z/>/svg>, bgColor: bg-red-50 }, Return Temp: { value: latest.returnTemp_C, unit: °C, icon: svg xmlnshttp://www.w3.org/2000/svg width24 height24 viewBox0 0 24 24 fillnone stroke#3b82f6 stroke-width2 stroke-linecapround stroke-linejoinround>path dM14 4v10.54a4 4 0 1 1-4 0V4a2 2 0 0 1 4 0Z/>/svg>, bgColor: bg-blue-50 }, Temp. Difference (ΔT): { value: latest.calculated_tempDifference_C, unit: °C, icon: svg xmlnshttp://www.w3.org/2000/svg width24 height24 viewBox0 0 24 24 fillnone stroke#f59e0b stroke-width2 stroke-linecapround stroke-linejoinround>path dM18 16v-8m-6 8V8m-6 8v-4/>/svg>, bgColor: bg-amber-50 }, Flow Rate: { value: latest.flowRate_m3_hr, unit: m³/hr, icon: svg xmlnshttp://www.w3.org/2000/svg width24 height24 viewBox0 0 24 24 fillnone stroke#0ea5e9 stroke-width2 stroke-linecapround stroke-linejoinround>path dM3 12h18m0 0l-6-6m6 6l-6 6/>/svg>, bgColor: bg-sky-50 }, Power: { value: latest.calculated_power_kW, unit: kW, icon: svg xmlnshttp://www.w3.org/2000/svg width24 height24 viewBox0 0 24 24 fillnone stroke#a855f7 stroke-width2 stroke-linecapround stroke-linejoinround>path dM13 2 3 14h9l-1 8 10-12h-9l1-8z/>/svg>, bgColor: bg-purple-50 }, Cost for Interval: { value: formatCurrency(latest.cost_for_interval_eur), unit: , icon: svg xmlnshttp://www.w3.org/2000/svg width24 height24 viewBox0 0 24 24 fillnone stroke#10b981 stroke-width2 stroke-linecapround stroke-linejoinround>circle cx8 cy8 r6/>path dM18.09 10.37A6 6 0 1 1 10.34 18/>path dM7 6h1v4/>path dm16.71 13.88.7.71-2.82 2.82/>/svg>, bgColor: bg-emerald-50 } }; metricsContainer.innerHTML Object.entries(metrics) .map((key, {value, unit, icon, bgColor}) > createMetricCard(key, value, unit, icon, bgColor)) .join(); renderCharts(history); } function createMetricCard(key, value, unit, icon, bgColor) { let displayValue N/A; if (key.includes(Cost)) { displayValue value || €0.00; } else if (typeof value number) { displayValue value.toFixed(3); } return ` div classbg-white p-4 rounded-lg shadow-md hover:shadow-lg transition-shadow> div classflex items-center space-x-4> div class${bgColor} p-3 rounded-full> ${icon} /div> div classflex-1> p classtext-sm text-gray-500>${key}/p> p classtext-xl font-bold text-gray-900>${displayValue} ${unit || }/p> /div> /div> /div>`; } function renderMap() { if (mapInstance) return; const lat 54.00468360577144; const lng -6.40054998664358; mapInstance L.map(map-container).setView(lat, lng, 15); L.tileLayer(https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png, { attribution: © a hrefhttps://www.openstreetmap.org/copyright>OpenStreetMap/a> contributors }).addTo(mapInstance); L.marker(lat, lng).addTo(mapInstance).bindPopup(Dundalk Town Hall).openPopup(); } function renderCharts(history) { // Sort history by timestamp const sortedHistory (history || ).sort((a, b) > a.timestamp - b.timestamp); // Only show data from last 48 hours const twoDaysAgo Date.now() - (48 * 60 * 60 * 1000); const recentHistory sortedHistory.filter(d > d.timestamp > twoDaysAgo); if (recentHistory.length 0) { // Show empty state message document.getElementById(temp-flow-chart).parentElement.innerHTML p classtext-center text-gray-500 my-8>No data available yet. Charts will populate as data arrives./p>; document.getElementById(power-cost-chart).parentElement.innerHTML p classtext-center text-gray-500 my-8>No data available yet. Charts will populate as data arrives./p>; return; } const labels recentHistory.map(d > d.timestamp); // Temperature & Flow Chart const tempFlowData { labels: labels, datasets: { label: Forward Temp (°C), data: recentHistory.map(d > ({ x: d.timestamp, y: d.forwardTemp_C })), borderColor: #dc2626, backgroundColor: rgba(220, 38, 38, 0.1), yAxisID: y_temp, tension: 0.1, fill: true, pointRadius: 3, pointHoverRadius: 5 }, { label: Return Temp (°C), data: recentHistory.map(d > ({ x: d.timestamp, y: d.returnTemp_C })), borderColor: #3b82f6, backgroundColor: rgba(59, 130, 246, 0.1), yAxisID: y_temp, tension: 0.1, fill: true, pointRadius: 3, pointHoverRadius: 5 }, { label: Flow Rate (m³/hr), data: recentHistory.map(d > ({ x: d.timestamp, y: d.flowRate_m3_hr })), borderColor: #0ea5e9, backgroundColor: rgba(14, 165, 233, 0.1), yAxisID: y_flow, tension: 0.1, fill: true, pointRadius: 3, pointHoverRadius: 5 } }; const tempFlowAxes { x: { type: time, time: { tooltipFormat: PP p, displayFormats: { hour: HH:mm, day: MMM dd } }, title: { display: true, text: Time } }, y_temp: { type: linear, position: left, title: { display: true, text: Temperature (°C) }, beginAtZero: false }, y_flow: { type: linear, position: right, title: { display: true, text: Flow Rate (m³/hr) }, grid: { drawOnChartArea: false }, beginAtZero: true } }; drawChart(temp-flow-chart, tempFlowData, tempFlowAxes); // Power & Cost Chart const powerCostData { labels: labels, datasets: { label: Power (kW), data: recentHistory.map(d > ({ x: d.timestamp, y: d.calculated_power_kW })), borderColor: #a855f7, backgroundColor: rgba(168, 85, 247, 0.1), yAxisID: y_power, tension: 0.1, fill: true, pointRadius: 3, pointHoverRadius: 5 }, { label: Cost (€), data: recentHistory.map(d > ({ x: d.timestamp, y: d.cost_for_interval_eur })), borderColor: #10b981, backgroundColor: rgba(16, 185, 129, 0.1), yAxisID: y_cost, tension: 0.1, fill: true, pointRadius: 3, pointHoverRadius: 5 } }; const powerCostAxes { x: { type: time, time: { tooltipFormat: PP p, displayFormats: { hour: HH:mm, day: MMM dd } }, title: { display: true, text: Time } }, y_power: { type: linear, position: left, title: { display: true, text: Power (kW) }, beginAtZero: true }, y_cost: { type: linear, position: right, title: { display: true, text: Cost per Interval (€) }, grid: { drawOnChartArea: false }, beginAtZero: true } }; drawChart(power-cost-chart, powerCostData, powerCostAxes); } function drawChart(chartId, data, axes) { const ctx document.getElementById(chartId)?.getContext(2d); if (!ctx) return; if (window.myChartschartId) window.myChartschartId.destroy(); window.myChartschartId new Chart(ctx, { type: line, data: data, options: { responsive: true, maintainAspectRatio: false, interaction: { mode: index, intersect: false, }, plugins: { legend: { display: true, position: top, }, tooltip: { mode: index, intersect: false, callbacks: { label: function(context) { let label context.dataset.label || ; if (label) label + : ; if (context.parsed.y ! null) { label + context.parsed.y.toFixed(3); } return label; } } } }, scales: axes } }); } window.toggleAutoRefresh function() { autoRefresh !autoRefresh; const btn document.getElementById(auto-refresh-btn); if (autoRefresh) { btn.textContent Auto-refresh: ON; btn.className px-4 py-2 bg-green-600 text-white rounded-lg hover:bg-green-700 transition-colors text-sm; fetchData(); } else { btn.textContent Auto-refresh: OFF; btn.className px-4 py-2 bg-gray-600 text-white rounded-lg hover:bg-gray-700 transition-colors text-sm; clearInterval(countdownInterval); countdownBarEl.style.width 0%; } }; // Initial fetch and set interval fetchData(); setInterval(() > { if (autoRefresh) { fetchData(); } }, FETCH_INTERVAL); /script>/body>/html>
View on OTX
|
View on ThreatMiner
Please enable JavaScript to view the
comments powered by Disqus.
Data with thanks to
AlienVault OTX
,
VirusTotal
,
Malwr
and
others
. [
Sitemap
]