NodeJS app weergeven p1monitor data

Voor het even snel bekijken waar onze zonnepanelen nu mee bezig zijn, heb ik een raspberry pi met daarop p1monitor gekoppeld aan onze slimme meter. p1monitor heeft een complete website geintegreerd, maar deze is niet responsive en schaalt helemaal niet lekker op een telefoon. En al die grafische metertjes zijn leuk, maar een eenvoudige tabelweergave is voor mij meer dan voldoende:

Dit is alles wat ik wil:

Een eenvoudig projectje, wat in een half uurtje is op te zetten.

Ik begin met het maken van een lege git repository op onze server. Deze repository wordt vervolgens op mijn chromebook gecloned naar een map die vervolgens in Visual Studio Code wordt geconfigureerd als workfolder. De ‘live’ app zal vervolgens met een pull bijgewerkt worden.

chromebook dev (vsc) — commit push –> central repository — pull — app

Hoe ik de git repo opzet, heb ik hier beschreven: New Git Repository.

In mijn geval heb ik een project gemaakt p1monitor-api. Deze ga ik eerst opzetten als een standaard nodejs express applicatie met ejs als template systeem. Deze app moet 2 dingen doen:

  1. data ophalen van de p1monitor api en deze ‘ombouwen’ naar een lokale api
  2. Deze api data op een heel eenvoudige website tonen, met een refresh-rate van 10 seconden.

Opzetten van een express applicatie (waarbij ik ervanuit ga dat een draaiende nodejs applicatie is geinstalleerd) is een fluitje van een cent. Draai daarvoor het volgende commando vanuit de werkfolder:

npx express-generator --view ejs --css --git

Na uitvoer van dit commando is dit de projectmap structuur:

Om de boel initieel draaiend te krijgen, voer ik in de folder het volgende 2 commando’s uit:

npm install
npm start

De eerste voert de installatie van de packages uit de package.json uit en het tweede commando start de applicatie op poort 3000.

Start in een browser de volgende url: localhost:3000 en als alles goed is krijg je deze pagina voorgeschoteld:

Het fundament van de applicatie werkt nu.

Het gaat hier om SPA een single page die gevoed wordt met data uit een rest api. Laten we met het eenvoudigste deel eerst verder gaan. Het allereenvoudigst nu is om de index.ejs aan te passen. Er zou ook voor een fixed index.html kunnen worden gekozen. Maar dat is voor nu meer aanpaswerk in de routers. Er wordt geen dynamic pagina data geproduceerd. De index.ejs is 100% html.

index.ejs:

<!DOCTYPE html>
<html>
  <head>
    <title>P1 data</title>
    <link rel='stylesheet' href='/stylesheets/style.css' />
  </head>
  <body>
    <h2>Huidig</h2>
    <p>Verbruik: <span id="wattcons"></span>&nbsp;<span>watt</span></p>
    <p>Levering: <span id="wattprod"></span>&nbsp;<span>watt</span></p>

    <h2>Dag</h2>
    <p>Verbruikt: <span id="kwhcons"></span>&nbsp;<span>kWh</span></p>
    <p>Geleverd: <span id="kwhprod"></span>&nbsp;<span>kWh</span></p>
    <br>
    <p>Gas: <span id="m3"></span>&nbsp;<span>m<sup>3</sup></span></p>
  </body>
</html>

Het ophalen van de data en deze realtime weergeven wordt met een brokje javascript gedaan. Omdat dit een zo minimale website is, heb ik het javascript in de body geplaatst. Om te beginnen heb ik Axios als http handler gebruikt:

<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

Vervolgens het script om api data op te halen (2 endpoints) en dit in de website te parsen.

<script>

async function getData() {
  try {
    let endpoints = [
    './api/current',
    './api/day'
  ];

  Promise.all(endpoints.map((endpoint) => axios.get(endpoint))).then(([{data: current}, {data: day}] )=> {
        document.getElementById('wattcons').innerHTML=current.CONSUMPTION_W;
        document.getElementById('wattprod').innerHTML=current.PRODUCTION_W;
        document.getElementById('kwhcons').innerHTML=day.CONSUMPTION_DELTA_KWH.toFixed(1);
        document.getElementById('kwhprod').innerHTML=day.PRODUCTION_DELTA_KWH.toFixed(1);
        document.getElementById('m3').innerHTML=day.CONSUMPTION_GAS_DELTA_M3.toFixed(1);
      });
  } catch (error) {
    console.error(error);
  }
}

getData();
setInterval(function(){
   getData();
}, 10000);

</script>

Deze pagina laadt nu wel, maar zal in de console 404 meldingen geven. Er moeten nog 2 api’s worden toegevoegd. /api/day en /api/current/. Allereerst de router zelf. Deze maakt gebruik van Axios om data van de p1 rest api te halen en door de routen naar onze rest api. Installeer deze eerst (en save als dependency):

npm install axios -s

Voor de router zelf herbruik de user.js in de routes folder. Deze hernoem ik naar api.js en vervang alles met deze code:

const createError = require('http-errors');

const express = require('express');
const router = express.Router();
const axios = require('axios');

router.get('/day', async function(req, res, next) {
    try {
        const response = await axios.get('http://p1monitor/api/v1/powergas/day?limit=1&json=object');
        console.log(response.data[0]);
        res.json(response.data[0]);
    } catch (error) {
        console.error(error);
        res.json({message:error});
      }
});

router.get('/current', async function(req, res, next) {
    try {
        const response = await axios.get('http://p1monitor/api/v1/smartmeter?limit=1&json=object');
        //console.log(response.data[0]);
        res.json(response.data[0]);
    } catch (error) {
        console.error(error);
        res.json({message:error});
      }
});

/* GET users listing. */
router.get('/', async function(req, res, next) {
    res.render('p1');
});

module.exports = router;

Nu moet de api nog bekend worden gemaakt als router mogelijkheid. Hiervoor pas ik de user regel aan naar api in de app.js:

var indexRouter = require('./routes/index');
//var usersRouter = require('./routes/users');
var apiRouter = require('./routes/api');

en

app.use('/', indexRouter);
//app.use('/users', usersRouter);
app.use('/api', apiRouter);

Voordat dit alles geupload wordt naar de git repo, eerst nog 2 bestanden toevoegen .env en .gitignore. Die .env doen we nu nog even niks mee, maar de .gitignore wel. Zo hoeft de hele node_modules boom niet geimporteerd te worden. En nog wat andere directories ook niet. Er zijn talloze voorbeelden te vinden op internet, wat wel en wat niet. De mijne ziet er zo uit:

Deze variant werkt heel goed, binnen mijn eigen netwerk, waarbij aangenomen wordt dat de raspberry pi in de netwerk dns bekend is als p1monitor. Als je deze app ook buiten de deur wil gebruiken, dan zul je een portforward in je modem router moeten instellen. Deze instelling valt ver buiten de scope van deze blog en is per modem en provider anders. Voor de beeldvorming, bij ons thuis is het geconfigureerd in de fritzbox en is deze gekoppeld via een dynamic dns service.

Daarom toch nog maar even wat aanpassingen. Om de environment file beschikbaar te stellen, is het nodig om dotenv te installeren:

npm install dotenv -s

De .env file wordt nu gevuld met een aantal variabelen. Omdat ik deze app achter een proxie draai, is het in sommige gevallen nodig om het volledige pad op te nemen. Omdat ik meerdere apps draai, heb ik verschillende poortnummers. In ontwikkel is 3000 prima, maar in produktie zal het iets van 30006 worden. Het is de zevende app. Ook de url van de p1monitor is beter om die niet wereldkundig te maken. De eerste stap van security is de obscurity :-). Daarom 3 parameters, die ik in ontwikkel vul met ontwikkelwaardes:

Om dotenv te gebruiken, zet ik gewoonlijk deze regel ergens bovenin de app.js file, in ieder geval ergens voordat de config gebruikt moet worden.

require('dotenv').config()

Het gebruik van het poortnummer uit deze file wordt in de /bin/www file gebruikt. Hoeft niks voor te gebeuren.

Zie deze regel

Ik persoonlijk voeg aan het eind van deze file nog even een console message toe:

Als de app nu opnieuw gestart wordt, dan krijg je dit in de log te zien:

Vraag aan chatGPT: Ken je een goede voetreflex therapeut in Zeist.

Om een goede voetreflextherapeut in Zeist te vinden, raad ik je aan om de volgende stappen te volgen:

  1. Vraag om aanbevelingen: Vraag vrienden, familieleden of collega’s of ze een goede voetreflextherapeut in Zeist kennen. Persoonlijke aanbevelingen kunnen waardevol zijn.
  2. Online zoeken: Gebruik online zoekmachines en sociale media om voetreflextherapeuten in Zeist te vinden. Je kunt zoektermen zoals “voetreflextherapeut Zeist” gebruiken.
  3. Check recensies: Als je potentiële therapeuten hebt gevonden, zoek dan naar recensies en beoordelingen van hun diensten. Dit kan je een idee geven van de ervaringen van andere patiënten.
  4. Contact opnemen: Neem contact op met de therapeuten die je interesseren en stel vragen over hun achtergrond, ervaring en behandelingsaanpak. Dit kan je helpen om te bepalen of ze geschikt zijn voor jouw behoeften.
  5. Raadpleeg brancheorganisaties: Je kunt ook contact opnemen met brancheorganisaties voor complementaire en alternatieve geneeskunde, zoals de Vereniging van Nederlandse Reflexzone Therapeuten (VNRT), voor aanbevelingen.
  6. Overleg met je huisarts: Als je twijfelt of voetreflextherapie geschikt is voor jouw specifieke gezondheidssituatie, overleg dan met je huisarts voordat je een therapeut kiest.

Onthoud dat het belangrijk is om met een gekwalificeerde en erkende voetreflextherapeut te werken om de beste zorg te ontvangen.

Advies van Johannes : voetreflextherapie-zeist.nl

Aan alles komt een eind

In Oktober vorig jaar zijn we overgestapt van Ziggo naar glasvezel. Ons emailadres bleef nog wel bestaan, maar sinds vandaag krijg je direct een ‘Undelivered Mail Returned to Sender’ terug.

Weggaan van Ziggo was toch wel even een dingetje. Want je moet weten dat ik in 1994, toen ik nog in Wageningen studeerde, mee ging doen aan een studenteninternetproject. Daarvoor kreeg je een kabelmodem op je kamer die via de tv aansluiting was aangesloten op het universiteitsnetwerk. Het was de begintijd van internet, het www was net een jaar geleden uitgevonden en er bestonden een paar duizend internetpagina’s. Maar goed vanaf het allereerste begin had ik dus een kabelmodem. Eerst een 10 megabits, wat voor die tijd natuurlijk waanzinnig snel was. Iedereen zat nog met 24k4 modems te kloten met een xs4all verbinding ed de echt snellen hadden een 56k6 modem. En ik, ik had 10 Megabit. De verhouding was natuurlijk helemaal zoek.

Even een verhaaltje tussendoor. Je moet weten dat in de begintijd van internet bestonden er geen zoekmachines. Alles was met links aan elkaar vastgeknoopt. In je Mosaic browser moest je bookmarks van websites opslaan als referentie. Mosaic, de prehistorie van webbrowsen. Ver voordat Netscape, Chrome, Internet Explorer bestonden.

Maar goed met Joost, een vriend van me, had ik gehoord dat je ‘porno plaatjes’ op internet kon vinden. Dat is uiteindelijk een zoektocht geworden van een paar weken. En toen hadden we 1 zeer lage resolutie gif van een paar tieten gevonden. Later bleek dat we helemaal verkeerd zochten. Voor vunzigheid moest je niet op het www zijn, maar op een veel duisterder plek, de nieuwsgroepen. Daar werd de porno per kilo geupload – toen moest je de berichten nog wel handmatig decripten naar bruikbare plaatjes. En later toen ik werkte had ik een projectleider die avonden en nachten al die nieuwsgroepen leeg zat te slurpen. En alles op cd-roms brandde en uitdeelde op zijn werk. Was een beetje een vies mannetje.

Maar goed terug naar het kabelmodem. In 1994 had ik dus al een kabelmodem. En ik ben eigenlijk altijd bij ziggo en alle voorgangers gebleven. Ook toen ik verhuisde van de studentenflat naar een gewone flat en later naar Zeist. Tot afgelopen November heb ik dus nooit anders dan kabelinternet gehad. Maar afgelopen jaar hebben ze de hele wijk aangesloten op glasvezel en een aanbieder kwam met wel een heel scherpe prijs van 1gig verbinding voor een paar tientjes per maand. Dat scheelde me dit jaar ongeveer 450 euro. Geld waar je ook andere dingen voor kunt doen.

Na 28 jaar heb ik daarom afscheid genomen van de good old kabel. En om eerlijk te zijn, het bevalt goed.

Gas tarieven

Vandaag een offerte gekregen van een energieleverancier. Naam doet er niet zoveel toe. Ik schrok van de inhaligheid van onze overheid. Omdat wij niet op gas stoken en koken, verbruiken wij wat gas om te douchen. Hier gaan we van uit dat we zo rond de 300 kuub per jaar verstoken in onze huishouding.

In de nu voor me liggende offerte komen we dan op ruim 700 euro per jaar uit. Wie snoept er wat op van dit bedrag:

WieEenheidsprijsAantalBedrag% van totaal
Levering€ 0,76 (incl btw) per kuub300 kuub€ 22833%
Overheidsheffing (belasting€ 0,49 met daarover € 0,10 btw per kuub300 kuub€ 17825%
Vaste leveringskosten€ 7,79 per maand12 maanden€ 9313%
Netbeheerkosten Stedin€ 17,25 per maand12 maanden€ 20729%
Totaal€ 706

Vooral die kwart overheidsheffing. Zoals op de nota is het 0.49 per kuub zonder btw. Dat is een hele grote wtf. We betalen dus belasting over een belasting. Hoe fucking transparant wil je het hebben. Dat spekken van de staatskas, moeten we snel mee stoppen. En 700 euro waarvan 66% vaste kosten uitgeven om een beetje te douchen vind ik persoonlijk een iets minder plan.

Laat me niet teveel in de negatieve emotie blijven hangen en deze ombuigen naar positieve energie. Energie die er al is. De zon. Zonnepanelen hebben we al. Maar, zoals eerder gezegd, gas gebruiken we om te douchen. Kunnen we die zonneenergie niet gebruiken om te douchen en is een warmwaterboiler misschien een oplossing. Zo’n boiler ken ik nog van vroeger. Dat was altijd op = op en dan maar koud afdouchen en lekker door het huis schreeuwen: ‘Wie heeft %$#@^&*(&# al het water verbruikt’. Maar daar worden we hard van.

Maar het kan nog extremer. Deze boiler aansluiten op electra EN een eigen zonnewarmtecollector. We hebben nog een stukje dak over (de dakkapel), kunnen we daar nou niet iets met een zonneboiler gaan doen. Ga ik even over nadenken.

Brodzich

Ofrûne nacht wie it wer brodzich waar.

Afgelopen nacht was het weer broeierig weer.

kriebelhaakjes

Deze stond nog op mijn lijstje. De accolade: { }. Ik probeerde laatst een groep uit te leggen om iets in RunMyJobs te configureren met accolades. Daar hadden ze nog niet van gehoord, dus ik ‘die tekens boven de vierkante haken’ en ‘die tekens rechts van de P op je toetsenbord’…. En de reaktie: “oooooooooh die, dat noemen wij ‘kriebelhaakjes'”.

Dat zijn de momenten dat ik meestal toch wel even stil val 🙂