ctucx.git: nixfiles

ctucx' nixfiles

commit 53fe5ec764a520b9f115a7b28d198ab69ec2d3b3
parent ff62bafb789c6aa57d680fe3fe6da2551ba22bbb
Author: Leah (ctucx) <git@ctu.cx>
Date: Fri, 9 Dec 2022 22:30:13 +0100

machines/lollo/smarthome: add mqtt-webui
6 files changed, 329 insertions(+), 0 deletions(-)
M
flake.lock
|
25
+++++++++++++++++++++++++
M
flake.nix
|
8
++++++++
M
machines/lollo/smarthome/default.nix
|
2
++
A
machines/lollo/smarthome/mqtt-webui-config.nix
|
254
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A
machines/lollo/smarthome/mqtt-webui.nix
|
38
++++++++++++++++++++++++++++++++++++++
M
pkgs/default.nix
|
2
++
diff --git a/flake.lock b/flake.lock
@@ -225,6 +225,30 @@
         "url": "file:///tmp/nix-secrets"
       }
     },
+    "mqtt-webui": {
+      "inputs": {
+        "flake-utils": [
+          "flake-utils"
+        ],
+        "nixpkgs": [
+          "nixpkgs"
+        ]
+      },
+      "locked": {
+        "lastModified": 1670619364,
+        "narHash": "sha256-zujFDUFOIqIllkP7yKqBhhetxS6VHOO63JZMsV5QPBE=",
+        "ref": "master",
+        "rev": "4f95bfd818d24ddb758fcd8b6e0f1f385d39b09c",
+        "revCount": 180,
+        "type": "git",
+        "url": "https://git.ctu.cx/mqtt-webui"
+      },
+      "original": {
+        "ref": "master",
+        "type": "git",
+        "url": "https://git.ctu.cx/mqtt-webui"
+      }
+    },
     "nix-eval-jobs": {
       "inputs": {
         "flake-utils": [

@@ -324,6 +348,7 @@
         "home-manager": "home-manager",
         "lacrosse2mqtt": "lacrosse2mqtt",
         "local-secrets": "local-secrets",
+        "mqtt-webui": "mqtt-webui",
         "nix-std": "nix-std",
         "nixpkgs": "nixpkgs",
         "nixpkgsUnstable": "nixpkgsUnstable",
diff --git a/flake.nix b/flake.nix
@@ -94,6 +94,14 @@
       inputs.flake-utils.follows = "flake-utils";
     };
 
+    mqtt-webui = {
+      type  = "git";
+      url   = "https://git.ctu.cx/mqtt-webui";
+      ref   = "master";
+      inputs.nixpkgs.follows     = "nixpkgs";
+      inputs.flake-utils.follows = "flake-utils";
+    };
+
     local-secrets.url = "/tmp/nix-secrets";
   };
 
diff --git a/machines/lollo/smarthome/default.nix b/machines/lollo/smarthome/default.nix
@@ -11,6 +11,8 @@
     ./lacrosse2mqtt.nix
 
     ./influxdb2.nix
+
+    ./mqtt-webui.nix
   ];
 
 }
diff --git a/machines/lollo/smarthome/mqtt-webui-config.nix b/machines/lollo/smarthome/mqtt-webui-config.nix
@@ -0,0 +1,253 @@
+let
+
+  Switch = name: topic: {
+    title         = name;
+    type          = "switch";
+    icon          = "icons/power_button.png";
+    topic.get     = topic;
+    topic.set     = "${topic}/set";
+    transform.get = "return (message.state == 'ON') ? true : false";
+    transform.set = "return JSON.stringify({state: (input) ? 'ON' : 'OFF'})";
+  };
+
+  BrighnessSlider = name: topic: {
+    title           = name;
+    type            = "slider";
+    icon            = "icons/bulb.png";
+    sliderMinValue  = 0;
+    sliderMaxValue  = 254;
+    sliderStepValue = 1;
+    topic.get       = topic;
+    topic.set       = "${topic}/set";
+    transform.get   = "return message.brightness";
+    transform.set   = "return JSON.stringify({brightness: Number(input)})";
+  };
+
+  ColorTemperatureSlider = name: topic: {
+    title           = name;
+    type            = "slider";
+    icon            = "icons/bulb.png";
+    sliderMinValue  = 250;
+    sliderMaxValue  = 454;
+    sliderStepValue = 1;
+    topic.get       = topic;
+    topic.set       = "${topic}/set";
+    transform.get   = "return message.color_temp";
+    transform.set   = "return JSON.stringify({color_temp: Number(input)})";
+  };
+
+  DimmableLamp = name: topic: {
+    title = name;
+    items = [
+      (Switch          "Power"     topic)
+      (BrighnessSlider "Brighness" topic)
+    ];
+  };
+
+  WhiteSpectrumLamp = name: topic: {
+    title = name;
+    items = [
+      (Switch                 "Power"             topic)
+      (BrighnessSlider        "Brighness"         topic)
+      (ColorTemperatureSlider "Color Temperature" topic)
+    ];
+  };
+
+  ColorSpectrumLamp = name: topic: {
+    title = name;
+    items = [
+      (Switch                 "Power"             topic)
+      (BrighnessSlider        "Brighness"         topic)
+      (ColorTemperatureSlider "Color Temperature" topic)
+
+      {
+        title           = "Color";
+        type            = "select";
+        icon            = "icons/bulb.png";
+        topic.get       = topic;
+        topic.set       = "${topic}/set";
+        transform.get   = "return message.color.x + ','+message.color.y";
+        transform.set   = "return JSON.stringify({color: {x: input.split(',')[0], y: input.split(',')[1]}})";
+        selectOptions   = [
+          {
+            label = "Red";
+            value = "0.71,0.26";
+          }
+          {
+            label = "Green";
+            value = "0.19,0.78";
+          }
+          {
+            label = "Blue";
+            value = "0.09,0.13";
+          }
+        ];
+      }
+    ];
+  };
+
+
+in {
+
+  pages =  [
+    {
+      id        = "mainpage";
+      icon     = "favicon-512x512.png";
+      title    = "Smart-Home";
+      sections = [
+        {
+          title = "Rooms";
+          items = [
+            {
+              title = "Leah's room";
+              type = "text";
+              icon = "icons/electric_range.png";
+              link = "#leah";
+            }
+            {
+              title = "Isa's room";
+              type = "text";
+              icon = "icons/electric_range.png";
+              link = "#isa";
+            }
+          ];
+        }
+
+        (WhiteSpectrumLamp "Hallway: Ceiling Light" "zigbee2mqtt/ikea_lamp_hallway")
+
+        (WhiteSpectrumLamp "Kitchen: Ceiling Light" "zigbee2mqtt/ikea_lamp_kitchen")
+
+        (WhiteSpectrumLamp "Bathroom: Ceiling Light" "zigbee2mqtt/ikea_lamp_bathroom")
+
+       {
+          title = "Temperature-Sensors";
+          items = [
+            {
+              title     = "Fridge";
+              type      = "text";
+              topic     = "lacrosse2mqtt/33";
+              icon      = "icons/temperature.png";
+              transform = "return Math.round((message.temperature + Number.EPSILON) * 100) / 100 + ' °C'";
+            }
+            {
+              title     = "Bathroom";
+              type      = "text";
+              topic     = "lacrosse2mqtt/5";
+              icon      = "icons/temperature.png";
+              transform = "return Math.round((message.temperature + Number.EPSILON) * 100) / 100 + ' °C - ' + message.humidity + ' %'";
+            }
+          ];
+        }
+      ];
+    }
+
+    {
+      id       = "leah";
+      icon     = "favicon-512x512.png";
+      title    = "Leah's room";
+      sections = [
+        (WhiteSpectrumLamp "Ceiling Light" "zigbee2mqtt/ikea_lamp_l")
+
+        (DimmableLamp "Desk" "zigbee2mqtt/led_stripe_desk")
+
+        (ColorSpectrumLamp "RGB Lamp" "zigbee2mqtt/ikea_lamp_l_rgb")
+
+        {
+          title = "Power-Meter";
+          items = [
+            {
+              title     = "Voltage";
+              type      = "text";
+              topic     = "sdm2mqtt/leah";
+              icon      = "icons/power.png";
+              transform = "return Math.round((message.voltage + Number.EPSILON) * 100) / 100 + ' V'";
+            }
+            {
+              title     = "Power";
+              type      = "text";
+              topic     = "sdm2mqtt/leah";
+              icon      = "icons/power.png";
+              transform = "return Math.round((message.power + Number.EPSILON) * 100) / 100 + ' W'";
+            }
+            {
+              title     = "Frequency";
+              type      = "text";
+              topic     = "sdm2mqtt/leah";
+              icon      = "icons/power.png";
+              transform = "return message.frequency + ' Hz'";
+            }
+            {
+              title     = "cos φ";
+              type      = "text";
+              topic     = "sdm2mqtt/leah";
+              icon      = "icons/power.png";
+              transform = "return Math.round((message.cosphi + Number.EPSILON) * 100) / 100";
+            }
+            {
+              title     = "Total Import";
+              type      = "text";
+              topic     = "sdm2mqtt/leah";
+              icon      = "icons/power.png";
+              transform = "return Math.round((message.import + Number.EPSILON) * 100) / 100 + ' kWh'";
+            }
+          ];
+        }
+
+        {
+          title = "Temperature-Sensors";
+          items = [
+            {
+              title     = "Temperature";
+              type      = "text";
+              topic     = "lacrosse2mqtt/3a";
+              icon      = "icons/temperature.png";
+              transform = "return Math.round((message.temperature + Number.EPSILON) * 100) / 100 + ' °C'";
+            }
+          ];
+        }
+      ];
+    }
+
+    {
+      id       = "isa";
+      icon     = "favicon-512x512.png";
+      title    = "Isa's room";
+      sections = [
+        (WhiteSpectrumLamp "Ceiling Light" "zigbee2mqtt/ikea_lamp_i")
+
+        (ColorSpectrumLamp "RGB Lamp" "zigbee2mqtt/ikea_lamp_i_rgb")
+
+        {
+          title = "Switches";
+          items = [
+            (Switch "Desk (L)" "zigbee2mqtt/ikea_control_outlet_i_desk_l")
+            (Switch "Desk (R)" "zigbee2mqtt/ikea_control_outlet_i_desk_r")
+          ];
+        }
+
+        {
+          title = "Temperature-Sensors";
+          items = [
+            {
+              title     = "Temperature";
+              type      = "text";
+              topic     = "lacrosse2mqtt/3c";
+              icon      = "icons/temperature.png";
+              transform = "return Math.round((message.temperature + Number.EPSILON) * 100) / 100 + ' °C'";
+            }
+            {
+              title     = "Humidity";
+              type      = "text";
+              topic     = "lacrosse2mqtt/3c";
+              icon      = "icons/thermostat.png";
+              transform = "return message.humidity + ' %'";
+            }
+          ];
+        }
+
+      ];
+    }
+
+  ];
+
+}+
\ No newline at end of file
diff --git a/machines/lollo/smarthome/mqtt-webui.nix b/machines/lollo/smarthome/mqtt-webui.nix
@@ -0,0 +1,37 @@
+{ inputs, lib, pkgs, ... }:
+
+let
+
+  configFile = pkgs.writeTextDir "config.json" (builtins.toJSON (import ./mqtt-webui-config.nix));
+
+in {
+
+  services = {
+    nginx    = {
+      enable = true;
+      virtualHosts."smart.home.ctu.cx" = {
+        enableACME = true;
+        forceSSL   = true;
+        kTLS       = true;
+
+        locations  = {
+          "/" = {
+            root  = "${pkgs.buildEnv {
+              name  = "mqtt-webui-env";
+              paths = [
+                pkgs.mqtt-webui
+                configFile
+              ];
+            }}/";
+          };
+          "/mqtt" = {
+            proxyPass       = "http://127.0.0.1:9005";
+            proxyWebsockets = true;
+          };
+        };
+      };
+    };
+
+  };
+
+}+
\ No newline at end of file
diff --git a/pkgs/default.nix b/pkgs/default.nix
@@ -13,6 +13,8 @@
 
       sdm2mqtt               = inputs.sdm2mqtt.packages."${currentSystem}".default;
       lacrosse2mqtt          = inputs.lacrosse2mqtt.packages."${currentSystem}".default;
+      mqtt-webui             = inputs.mqtt-webui.packages."${currentSystem}".default;
+
       pleroma                = prev.pleroma.overrideAttrs (old: {
         patches = [
          ./0001-PATCH-Separate-webfinger-domain-from-host-domain.patch