neiam
/lambent_ex
Lambent Aether 5
public · Issues · Pulls 1 · Labels · Forks · Compare · Actions success · Badges · Packages
Log in to mark this repository.
machine and links working now, cleaned UI and ported afterdark over
962e964 · gmorell · 2022-12-12 06:08
Files changed
modified
assets/tailwind.config.js
+17
−0
| 4 | 4 | const plugin = require("tailwindcss/plugin") |
| 5 | 5 | |
| 6 | 6 | module.exports = { |
| 7 | + daisyui: { | |
| 8 | + themes: [ | |
| 9 | + { | |
| 10 | + afterdark: { | |
| 11 | + "primary": "#7B79B5", | |
| 12 | + "secondary": "#ACABD5", | |
| 13 | + "accent": "#fef3c7", | |
| 14 | + "neutral": "#38357F", | |
| 15 | + "base-100": "#201D65", | |
| 16 | + "info": "#7dd3fc", | |
| 17 | + "success": "#a7f3d0", | |
| 18 | + "warning": "#fef08a", | |
| 19 | + "error": "#fca5a5", | |
| 20 | + }, | |
| 21 | + }, | |
| 22 | + ] | |
| 23 | + }, | |
| 7 | 24 | content: [ |
| 8 | 25 | "./js/**/*.js", |
| 9 | 26 | "../lib/*_web.ex", |
modified
lib/lambent_ex/link.ex
+35
−35
| 4 | 4 | |
| 5 | 5 | @pubsub_name LambentEx.PubSub |
| 6 | 6 | @pubsub_topic "machine-" |
| 7 | + @pubsub_topic_idx "links_idx" | |
| 7 | 8 | |
| 8 | − @registry :lambent | |
| 9 | + @registry :lambent_links | |
| 9 | 10 | |
| 10 | 11 | def start_link(opts) do |
| 11 | 12 | GenServer.start_link(__MODULE__, opts, name: via_tuple("link-#{opts[:name]}")) |
| 12 | 13 | end |
| 13 | 14 | |
| 14 | − def init(_opts) do | |
| 15 | − Phoenix.PubSub.subscribe(@pubsub_name, @pubsub_topic) | |
| 15 | + def init(opts) do | |
| 16 | + Process.send_after(self(), :publish, 50) | |
| 17 | + {:ok, opts} = Keyword.validate(opts, [:source, :target, :name]) | |
| 18 | + Phoenix.PubSub.subscribe(@pubsub_name, @pubsub_topic <> opts[:source]) | |
| 19 | + | |
| 20 | + # todo | |
| 21 | + # publish-pause-siblings | |
| 22 | + # subscribe-pause-siblings | |
| 16 | 23 | |
| 17 | − # gets overwritten | |
| 18 | 24 | { |
| 19 | 25 | :ok, |
| 20 | − %{} | |
| 26 | + %{ | |
| 27 | + source: opts[:source], | |
| 28 | + target: opts[:target], | |
| 29 | + name: opts[:name], | |
| 30 | + enabled: true, | |
| 31 | + } | |
| 21 | 32 | } |
| 22 | 33 | end |
| 23 | 34 | |
| 24 | 35 | defp via_tuple(name), do: {:via, Registry, {@registry, name}} |
| 25 | 36 | |
| 37 | + defp publish(state) do | |
| 38 | + %{ | |
| 39 | + name: state[:name], | |
| 40 | + source: state[:source], | |
| 41 | + target: state[:target], | |
| 42 | + enabled: state[:enabled] | |
| 43 | + } | |
| 44 | + end | |
| 45 | + | |
| 26 | 46 | def handle_info({:publish, data}, state) do |
| 27 | − IO.puts("hhh") | |
| 28 | − | |
| 29 | − dvcs = | |
| 30 | − [ | |
| 31 | − {192, 168, 13, 203}, | |
| 32 | − {192, 168, 13, 209}, | |
| 33 | − {192, 168, 13, 211}, | |
| 34 | − {192, 168, 13, 214}, | |
| 35 | − {192, 168, 13, 215}, | |
| 36 | − {192, 168, 13, 222}, | |
| 37 | − {192, 168, 13, 225}, | |
| 38 | − {192, 168, 13, 228}, | |
| 39 | − {192, 168, 13, 230}, | |
| 40 | − {192, 168, 13, 241} | |
| 41 | − ] | |
| 42 | − | |
| 43 | − dvcs = [ | |
| 44 | − "10:52:1c:02:8c:12", | |
| 45 | − "10:52:1c:02:d4:d2", | |
| 46 | − "18:fe:34:d4:7a:b5", | |
| 47 | − "68:c6:3a:a4:d3:b6", | |
| 48 | − "8c:aa:b5:1b:46:09", | |
| 49 | − "a4:cf:12:b3:fc:b6", | |
| 50 | − "ec:fa:bc:c0:96:98", | |
| 51 | − | |
| 52 | − ] | |
| 53 | − | |
| 54 | − for i <- dvcs do | |
| 55 | − LambentEx.Scan.ESP8266x7777.submit(i, data |> List.flatten) | |
| 47 | + case state[:enabled] do | |
| 48 | + true -> LambentEx.Scan.ESP8266x7777.submit(state[:target], data |> List.flatten) | |
| 49 | + false -> :ok | |
| 56 | 50 | end |
| 57 | − # IO.inspect(data) | |
| 58 | 51 | |
| 59 | 52 | {:noreply, state} |
| 60 | 53 | end |
| 54 | + | |
| 55 | + @impl true | |
| 56 | + def handle_info(:publish, state) do | |
| 57 | + Process.send_after(self(), :publish, 400) | |
| 58 | + Phoenix.PubSub.broadcast(@pubsub_name, @pubsub_topic_idx, {:publish, publish(state)}) | |
| 59 | + {:noreply, state} | |
| 60 | + end | |
| 61 | 61 | end |
modified
lib/lambent_ex/machine.ex
+39
−6
| 6 | 6 | |
| 7 | 7 | @pubsub_name LambentEx.PubSub |
| 8 | 8 | @pubsub_topic "machine-" |
| 9 | + @pubsub_topic_idx "machines_idx" | |
| 9 | 10 | |
| 10 | 11 | @speeds %{ |
| 11 | 12 | # 1 => :THOU, |
| 42 | 43 | |
| 43 | 44 | def init(opts) do |
| 44 | 45 | Process.send_after(self(), :step, 100) |
| 46 | + Process.send_after(self(), :publish, 50) | |
| 45 | 47 | {:ok, opts} = Keyword.validate(opts, [:step, :step_opts, :name, count: 300]) |
| 46 | 48 | cnt = opts[:count] |
| 47 | 49 |
| 62 | 64 | |
| 63 | 65 | {:ok, |
| 64 | 66 | %{ |
| 67 | + step: opts[:step], | |
| 65 | 68 | steps: pids, |
| 66 | 69 | name: opts[:name], |
| 67 | 70 | # todo configurable |
| 97 | 100 | # impls |
| 98 | 101 | |
| 99 | 102 | defp bmath(i, state) do |
| 100 | − (i * state.bright_curr / 255.0) |> trunc | |
| 103 | + (i * state.bright_curr / 255.0) |> round | |
| 104 | + end | |
| 105 | + | |
| 106 | + def stripstep(step) do | |
| 107 | + [_head, step] = step |> to_string |> String.split(".Steps.") | |
| 108 | + step | |
| 109 | + end | |
| 110 | + | |
| 111 | + defp id(state) do | |
| 112 | + step = state[:step] |> stripstep | |
| 113 | + [step, "x", state[:name]] |> Enum.join("") | |
| 114 | + end | |
| 115 | + | |
| 116 | + defp publish(state) do | |
| 117 | + %{ | |
| 118 | + id: id(state), | |
| 119 | + name: state[:name], | |
| 120 | + step: state[:step] |> stripstep, | |
| 121 | + speed: state[:speed], | |
| 122 | + cnt: state[:cnt], | |
| 123 | + bgt: state[:bright_curr] | |
| 124 | + } | |
| 101 | 125 | end |
| 102 | 126 | |
| 103 | 127 | @impl true |
| 107 | 131 | state[:steps] |
| 108 | 132 | |> Enum.map(&GenServer.cast(&1, :step)) |
| 109 | 133 | |
| 110 | − data = state[:steps] | |
| 111 | − |> Enum.map(&GenServer.call(&1, :read)) | |
| 112 | − |> Enum.map(fn x -> x |> Enum.map(fn y -> bmath(y, state) end) end) | |
| 113 | −# | |
| 114 | −# |> IO.inspect() | |
| 134 | + data = | |
| 135 | + state[:steps] | |
| 136 | + |> Enum.map(&GenServer.call(&1, :read)) | |
| 137 | + |> Enum.map(fn x -> x |> Enum.map(fn y -> bmath(y, state) end) end) | |
| 138 | + | |
| 139 | + # | |
| 140 | + # |> IO.inspect() | |
| 115 | 141 | Phoenix.PubSub.broadcast(@pubsub_name, @pubsub_topic <> state[:name], {:publish, data}) |
| 116 | 142 | {:noreply, bright_step(state)} |
| 117 | 143 | end |
| 118 | 144 | |
| 145 | + @impl true | |
| 146 | + def handle_info(:publish, state) do | |
| 147 | + Process.send_after(self(), :publish, 400) | |
| 148 | + Phoenix.PubSub.broadcast(@pubsub_name, @pubsub_topic_idx, {:publish, publish(state)}) | |
| 149 | + {:noreply, state} | |
| 150 | + end | |
| 151 | + | |
| 119 | 152 | def handle_info({:EXIT, pid, err}, state) do |
| 120 | 153 | IO.inspect(err) |
| 121 | 154 | {:noreply, state} |
modified
lib/lambent_ex/scan/8266-7777.ex
+68
−29
| 4 | 4 | require Logger |
| 5 | 5 | |
| 6 | 6 | alias LambentEx.Utils.Color, as: C |
| 7 | + alias LambentEx.Meta, as: M | |
| 7 | 8 | |
| 8 | 9 | @registry :lambent |
| 9 | 10 | @s "ꙭ📡" |
| 25 | 26 | %{ |
| 26 | 27 | interfaces: interfaces, |
| 27 | 28 | arps: %{}, |
| 28 | − devices: %{ | |
| 29 | − "10:52:1c:02:d4:d2" => %{ | |
| 30 | − "ip" => {192, 168, 13, 226}, | |
| 31 | − "name" => "AssFace3k", | |
| 32 | − "ord" => :rgb | |
| 33 | − } | |
| 34 | − }, | |
| 29 | + devices: %{}, | |
| 35 | 30 | socket: socket |
| 36 | 31 | }} |
| 37 | 32 | end |
| 56 | 51 | via_tuple("scan_8266") |> GenServer.cast({:submit, dvc, stream}) |
| 57 | 52 | end |
| 58 | 53 | |
| 54 | + def poke(dvc) do | |
| 55 | + via_tuple("scan_8266") |> GenServer.cast({:poke, dvc}) | |
| 56 | + end | |
| 57 | + | |
| 59 | 58 | def devices() do |
| 60 | 59 | via_tuple("scan_8266") |> GenServer.call(:get_devices) |
| 61 | 60 | end |
| 66 | 65 | def handle_cast({:rename_mac, mac, name}, state) do |
| 67 | 66 | d = state[:devices] |> Map.get(mac) |
| 68 | 67 | dev = state[:devices] |> Map.put(mac, d |> Map.put("name", name)) |
| 68 | + # write to ets | |
| 69 | + M.put_name(mac, name) | |
| 69 | 70 | {:noreply, %{state | devices: dev}} |
| 70 | 71 | end |
| 71 | 72 | |
| 72 | 73 | @impl true |
| 73 | 74 | def handle_cast({:rename_ip, ip, name}, state) do |
| 74 | − mac = state[:arps] |> Enum.map(fn {iface, arr} -> arr |> Enum.map(fn {k,v} -> {k,v} end) end) |> List.flatten |> Map.new |> Map.get(ip) | |
| 75 | + mac = | |
| 76 | + state[:arps] | |
| 77 | + |> Enum.map(fn {iface, arr} -> arr |> Enum.map(fn {k, v} -> {k, v} end) end) | |
| 78 | + |> List.flatten() | |
| 79 | + |> Map.new() | |
| 80 | + |> Map.get(ip) | |
| 81 | + | |
| 75 | 82 | d = state[:devices] |> Map.get(mac) |
| 76 | 83 | dvcs = state[:devices] |> Map.put(mac, d |> Map.put("name", name)) |
| 84 | + | |
| 85 | + M.put_name(mac, name) | |
| 77 | 86 | {:noreply, %{state | devices: dvcs}} |
| 78 | 87 | end |
| 79 | 88 |
| 81 | 90 | def handle_cast({:reorder, mac, ord}, state) do |
| 82 | 91 | d = state[:devices] |> Map.get(mac) |
| 83 | 92 | dev = state[:devices] |> Map.put(mac, d |> Map.put("ord", ord)) |
| 93 | + | |
| 94 | + M.put_ord(mac, ord) | |
| 84 | 95 | {:noreply, %{state | devices: dev}} |
| 85 | 96 | end |
| 86 | 97 | |
| 87 | 98 | @impl true |
| 88 | 99 | def handle_cast({:submit, dvc, stream}, state) do |
| 89 | − IO.inspect(state[:devices]) | |
| 90 | − IO.inspect(dvc) | |
| 91 | − | |
| 92 | 100 | case state[:devices] |> Map.get(dvc) do |
| 93 | 101 | nil -> |
| 94 | − IO.inspect(:nd) | |
| 95 | 102 | {:noreply, state} |
| 96 | 103 | |
| 97 | 104 | device -> |
| 100 | 107 | end |
| 101 | 108 | end |
| 102 | 109 | |
| 110 | + @impl true | |
| 111 | + def handle_cast({:poke, dvc}, state) do | |
| 112 | + case state[:devices] |> Map.get(dvc) do | |
| 113 | + nil -> | |
| 114 | + {:noreply, state} | |
| 115 | + | |
| 116 | + device -> | |
| 117 | + for {i,c} <- [{10, C.cre}, {100, C.cbe}, {200, C.cge}, {300, C.cce}, {400, C.cye}, {500, C.cme}, {600, C.cke}] do | |
| 118 | + Process.send_after(self(), {:send, device, c}, i) | |
| 119 | + end | |
| 120 | + {:noreply, state} | |
| 121 | + end | |
| 122 | + | |
| 123 | + {:noreply, state} | |
| 124 | + end | |
| 125 | + | |
| 126 | + @impl true | |
| 103 | 127 | def handle_call(:get_devices, _from, state) do |
| 104 | 128 | {:reply, state[:devices], state} |
| 105 | 129 | end |
| 130 | 154 | |
| 131 | 155 | case device |> Map.get(:ord) do |
| 132 | 156 | :rgb -> |
| 133 | − chunked | |
| 157 | + chunked |> Enum.map(fn [r, g, b] -> [g,r,b] end) | |
| 134 | 158 | |
| 135 | 159 | :grb -> |
| 136 | − chunked |> Enum.map(fn [r, g, b] -> [g, r, b] end) | |
| 160 | + chunked |> Enum.map(fn [r, g, b] -> [r, g, b] end) | |
| 137 | 161 | |
| 138 | 162 | :rgbww -> |
| 139 | − chunked |> Enum.map(fn [r, g, b] -> [r, g, b, Enum.min(C.wrgb([r, g, b]), r)] end) | |
| 163 | + chunked |> Enum.map(fn [r, g, b] -> [g,r,b, Enum.min(C.wrgb([r, g, b]), r)] end) | |
| 140 | 164 | |
| 141 | 165 | :rgbnw -> |
| 142 | − chunked |> Enum.map(fn [r, g, b] -> [r, g, b, C.wrgb([r, g, b])] end) | |
| 166 | + chunked |> Enum.map(fn [r, g, b] -> [g,r,b, C.wrgb([r, g, b])] end) | |
| 143 | 167 | |
| 144 | 168 | :rgbcw -> |
| 145 | − chunked |> Enum.map(fn [r, g, b] -> [r, g, b, Enum.min([C.wrgb([r, g, b]), b])] end) | |
| 169 | + chunked |> Enum.map(fn [r, g, b] -> [g,r,b, Enum.min([C.wrgb([r, g, b]), b])] end) | |
| 146 | 170 | |
| 147 | 171 | :rgbaw -> |
| 148 | − chunked |> Enum.map(fn [r, g, b] -> [r, g, b, C.argb([r, g, b]), C.wrgb([r, g, b])] end) | |
| 172 | + chunked |> Enum.map(fn [r, g, b] -> [g,r,b, C.argb([r, g, b]), C.wrgb([r, g, b])] end) | |
| 149 | 173 | |
| 150 | 174 | :rgbxw -> |
| 151 | − chunked |> Enum.map(fn [r, g, b] -> [r, g, b, 0] end) | |
| 175 | + chunked |> Enum.map(fn [r, g, b] -> [g,r,b, 0] end) | |
| 152 | 176 | |
| 153 | 177 | nil -> |
| 154 | − chunked | |
| 178 | + chunked |> Enum.map(fn [r, g, b] -> [g,r,b] end) | |
| 155 | 179 | end |
| 156 | 180 | |> List.flatten() |
| 157 | 181 | end |
| 161 | 185 | stream |
| 162 | 186 | end |
| 163 | 187 | |
| 164 | − | |
| 165 | − | |
| 166 | 188 | @impl true |
| 167 | 189 | def handle_call(_msg, _from, state) do |
| 168 | 190 | {:reply, :ok, state} |
| 243 | 265 | {:noreply, state} |
| 244 | 266 | end |
| 245 | 267 | |
| 268 | + def handle_info({:send, dvc, stream}, state) do | |
| 269 | + | |
| 270 | + :gen_udp.send(state.socket, dvc["ip"], 7777, rgb_shift(stream, dvc) |> rgb_stream) | |
| 271 | + {:noreply, state} | |
| 272 | + end | |
| 273 | + | |
| 246 | 274 | defp add_type(devices) do |
| 247 | − devices |> Enum.map(fn {k,v} -> {k, v |> Map.put("type", "8266-7777")} end) |> Map.new | |
| 275 | + devices |> Enum.map(fn {k, v} -> {k, v |> Map.put("type", "8266-7777")} end) |> Map.new() | |
| 248 | 276 | end |
| 249 | 277 | |
| 250 | 278 | @impl true |
| 251 | 279 | def handle_info(:publish, state) do |
| 252 | 280 | Process.send_after(self(), :publish, :timer.seconds(2)) |
| 253 | − Phoenix.PubSub.broadcast(@pubsub_name, "scan-82667777", {:publish, state[:devices] |> add_type}) | |
| 281 | + | |
| 282 | + Phoenix.PubSub.broadcast( | |
| 283 | + @pubsub_name, | |
| 284 | + "scan-82667777", | |
| 285 | + {:publish, state[:devices] |> add_type} | |
| 286 | + ) | |
| 287 | + | |
| 254 | 288 | {:noreply, state} |
| 255 | 289 | end |
| 256 | 290 | |
| 257 | − | |
| 258 | 291 | defp join_arps(new, state) do |
| 259 | 292 | arps = state[:arps] |
| 260 | 293 | |
| 261 | − result = arps |> Map.merge(new, fn _k, v1, v2 -> | |
| 262 | − v1 |> Map.merge(v2) | |
| 263 | − end) | |
| 294 | + result = | |
| 295 | + arps | |
| 296 | + |> Map.merge(new, fn _k, v1, v2 -> | |
| 297 | + v1 |> Map.merge(v2) | |
| 298 | + end) | |
| 299 | + | |
| 264 | 300 | %{state | arps: result} |
| 265 | 301 | end |
| 266 | 302 |
| 281 | 317 | |> Enum.reduce(fn x, y -> |
| 282 | 318 | Map.merge(x, y, fn _k, v1, v2 -> v2 ++ v1 end) |
| 283 | 319 | end) |
| 320 | + |> Enum.map(fn {k,v} -> {k, v |> Map.put("name", M.get_name(k)) |> Map.put("ord", M.get_ord(k))}end) | |
| 321 | + |> Enum.filter(fn {k, _v} -> k != nil end) | |
| 322 | + |> Map.new | |
| 284 | 323 | |
| 285 | − state |> Map.put(:devices, rez) | |
| 324 | + state |> Map.put(:devices, Map.merge(devices, rez)) | |
| 286 | 325 | end |
| 287 | 326 | |
| 288 | 327 | def get_valid_interfaces() do |
added
lib/lambent_ex/scan/meta.ex
+43
−0
| 1 | +defmodule LambentEx.Meta do | |
| 2 | + use GenServer | |
| 3 | + | |
| 4 | + @table :lex_metadata | |
| 5 | + | |
| 6 | + def init(arg) do | |
| 7 | + {:ok, table} = :dets.open_file(@table, [type: :set]) | |
| 8 | + | |
| 9 | + {:ok, %{table: table}} | |
| 10 | + end | |
| 11 | + | |
| 12 | + def start_link(arg) do | |
| 13 | + GenServer.start_link(__MODULE__, arg, name: __MODULE__) | |
| 14 | + end | |
| 15 | + | |
| 16 | + def get_name(mac) do | |
| 17 | + case :dets.lookup(@table, "name-#{mac}") do | |
| 18 | + [] -> | |
| 19 | + nil | |
| 20 | + | |
| 21 | + [{_key, value}] -> | |
| 22 | + value | |
| 23 | + end | |
| 24 | + end | |
| 25 | + | |
| 26 | + def get_ord(mac) do | |
| 27 | + case :dets.lookup(@table, "ord-#{mac}") do | |
| 28 | + [] -> | |
| 29 | + nil | |
| 30 | + | |
| 31 | + [{_key, value}] -> | |
| 32 | + value | |
| 33 | + end | |
| 34 | + end | |
| 35 | + | |
| 36 | + def put_name(key, value) do | |
| 37 | + :dets.insert(@table, {"name-#{key}", value}) | |
| 38 | + end | |
| 39 | + | |
| 40 | + def put_ord(key, value) do | |
| 41 | + :dets.insert(@table, {"ord-#{key}", value}) | |
| 42 | + end | |
| 43 | +end |
modified
lib/lambent_ex/supervision/component.ex
+2
−0
Click to load diff…
added
lib/lambent_ex/supervision/link.ex
+24
−0
Click to load diff…
modified
lib/lambent_ex/util/color.ex
+16
−0
Click to load diff…
modified
lib/lambent_ex_web/components/layouts/app.html.heex
+39
−5
Click to load diff…
modified
lib/lambent_ex_web/components/layouts/root.html.heex
+2
−2
Click to load diff…
modified
lib/lambent_ex_web/live/devices/index.ex
+11
−8
Click to load diff…
modified
lib/lambent_ex_web/live/devices/index.html.heex
+1
−1
Click to load diff…
modified
?
+0
−0
Click to load diff…
added
lib/lambent_ex_web/live/links/index.ex
+38
−0
Click to load diff…
added
lib/lambent_ex_web/live/links/index.html.heex
+30
−0
Click to load diff…
added
lib/lambent_ex_web/live/machines/index.ex
+78
−0
Click to load diff…
added
lib/lambent_ex_web/live/machines/index.html.heex
+41
−0
Click to load diff…
modified
lib/lambent_ex_web/router.ex
+4
−2
Click to load diff…
Parents: 1296a60