commit d222f6f761b5ddf3e11a48bd3806d12ebae0c438 Author: Dirk Heilig Date: Wed Oct 16 14:22:30 2024 +0200 first commit diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..1cd3bac --- /dev/null +++ b/Dockerfile @@ -0,0 +1,28 @@ +FROM debian:12 +RUN apt-get update +RUN apt-get upgrade -y +RUN apt-get install -y \ + php-cli php-json php-curl composer \ + php-pear php-dev \ + libmosquitto-dev libmosquitto1 mosquitto-clients \ + wget \ + procps \ + php-yaml \ + locales-all \ + git \ + build-essential \ + cmake + +WORKDIR /opt +RUN git clone https://github.com/nismoryco/Mosquitto-PHP.git +WORKDIR /opt/Mosquitto-PHP +RUN phpize +RUN ./configure +RUN make +RUN make install +RUN echo "extension=mosquitto.so" >/etc/php/8.2/mods-available/mosquitto.ini +RUN ln -s /etc/php/8.2/mods-available/mosquitto.ini /etc/php/8.2/cli/conf.d/20-mosquitto.ini + +ADD run.php /usr/local/bin/run + +ENTRYPOINT /usr/local/bin/run diff --git a/Readme.md b/Readme.md new file mode 100644 index 0000000..11d03bc --- /dev/null +++ b/Readme.md @@ -0,0 +1,25 @@ +# My Usage Dashboard +This script is used to calculate the energy consumption and coast since the last time the door was opened. + +It gets 2 values via mqtt, the door status and the current energy meter value. +With this Information, it gives the following outputs: + + - the energy amount in kwh as float. + - the coast in € as float. + - the coast in euro rounded to 2 decimal places as string, ready for displaying. + +all this topics will get a empty payload if the door is closed. + +## configuration + +The script is configured env vars: + +MQTT_HOST: the mqtt host to connect to +ENERGY_METER_TOPIC: the mqtt topic to get the energy meter value +DOOR_TOPIC: the mqtt topic to get the door status +ENERGY_PRICE: the price per kwh in € +OUTPUT_TOPIC_PREFIX: the mqtt topic to publish the outputs to + +optionally: +MQTT_USER: the user to connect with +MQTT_PASSWORD: the password to connect with diff --git a/devrun b/devrun new file mode 100755 index 0000000..e8772de --- /dev/null +++ b/devrun @@ -0,0 +1,9 @@ +#!/usr/bin/env bash +docker build -t mud . + +docker run --rm -it \ + -e "MQTT_HOST=$MQTT_HOST" \ + -e "ENERGY_METER_TOPIC=$ENERGY_METER_TOPIC" \ + -e "DOOR_TOPIC=$DOOR_TOPIC" \ + -e "OUTPUT_TOPIC_PREFIX=$OUTPUT_TOPIC_PREFIX" \ + mud \ No newline at end of file diff --git a/run.php b/run.php new file mode 100755 index 0000000..6f8a3eb --- /dev/null +++ b/run.php @@ -0,0 +1,114 @@ +#!/usr/bin/env php +setCredentials(getenv("MQTT_USER"), getenv("MQTT_PASS")); +} + +$c->connect(MQTT_HOST, 1883, 60); +$c->subscribe(ENERGY_METER_TOPIC, 2); +$c->subscribe(DOOR_TOPIC, 2); + +$c->onMessage(function (Message $message) { + switch ($message->topic) { + case getenv("ENERGY_COUNTER_TOPIC"): + energy($message->payload); + break; + case getenv("DOOR_TOPIC"): + door($message->payload); + break; + } +}); + +while (true) { + while ($lastOutput > time() - 10) { + $c->loop(1000); + } + output(); +} + +function door($newStatus) +{ + global $doorStatus, $energyCounter, $doorOpenEnergy, $doorOpenTime; + if (is_null($energyCounter)) { + return; + } + $newStatus = (bool) $newStatus; + if ($newStatus === $doorStatus) { + return; + } + $doorStatus = $newStatus; + if (!$newStatus) { + $doorOpenEnergy = $energyCounter; + $doorOpenTime = time(); + } + output(); +} +function energy($value) +{ + global $energyCounter; + $energyCounter = (float) $value; + output(); +} + +function output() +{ + global $doorStatus, + $energyCounter, + $doorOpenEnergy, + $doorOpenTime, + $lastOutput, + $c; + if ($doorStatus) { + $myUsage = $energyCounter - $doorOpenEnergy; + $myCost = $myUsage * ENERGY_PRICE; + $c->publish( + OUTPUT_TOPIC_PREFIX . "/used_energy_float", + strval($myUsage), + 2 + ); + $c->publish(OUTPUT_TOPIC_PREFIX . "/price_float", strval($myCost), 2); + $c->publish( + OUTPUT_TOPIC_PREFIX . "/price_string", + number_format($myCost, 2, ",", "."), + 2 + ); + } else { + $c->publish(OUTPUT_TOPIC_PREFIX . "/used_energy_float", "", 2); + $c->publish(OUTPUT_TOPIC_PREFIX . "/price_float", "", 2); + $c->publish(OUTPUT_TOPIC_PREFIX . "/price_string", "", 2); + } + $lastOutput = time(); +} +