불로장생 약신경과 피닉스 라이브뷰 구성 요소를 갖춘 사물인터넷 새장🐦

67450 단어 elixirnervesiotphoenix

총유기탄소

  • Introduction

  • The basic concept
  • Hardware

  • Setting up a new Elixir Nerves project
  • Creating our first Nerves project
  • Setting up WiFi and updating via SSH
  • Picam - Setting up a video stream
  • LiveView Components for the temperature and humidity sensor
  • Sending snaps to a telegram chat

  • Final Word
  • My learning resources
  • 소개


    우리는 크론기술대학에서 새로운 학사학위인 코드 & Context를 받았고 프로젝트 기반의 일을 사랑합니다.여전히 진행 중인 봉쇄 기간에 우리는 캠퍼스의 개방 공간과 어떤 관계를 맺기를 희망한다.
    2학기의 학습을 완성하기 위해서, 우리는 프로젝트의 소망이 하나 있다. 바로 원격 브라우저이다.우리뿐만 아니라 미래의 학생이나 완전한 외부인에게 캠퍼스를 탐색하는 선택을 주는 것은 매우 멋있고 우리에게 더욱 긴밀한 관계를 맺는 느낌을 줄 수 있다.
    우리는 불로장생 약신경과 봉황 라이브뷰로 사물인터넷 새집을 짓기로 했다.
    Elixir는 나에게 다른 프로그래밍 시각을 주었다. 나는 미래의 프로젝트에서 가능한 한 그것을 많이 사용할 것이다.내가 추천한 학습 자원의 링크는 이 문장의 끝에 첨부되어 있다.

    너 혼자 해봐.


    다음git 저장소에서 코드를 찾을 수 있습니다
    Take me to the git repository

    기본 개념


    Neurs는 Elixir에서 삽입식 시스템을 구축하는 데 사용하기 쉽고 기능이 강한 프레임워크입니다.
    나는 확실히 토드 레소드의 강연을 보라고 건의한다. "왜 당신의 다음 하드웨어 프로젝트는 신경으로 구축해야 합니까?"
    또한 Phoenix LiveView를 사용하여 다음과 같은 기능을 갖춘 실시간 대시보드를 구축할 수 있습니다.
  • LED 켜기 및 끄기(내장형 시스템 항목에 없을 수 있는 방법)
  • 식품 용기를 열고 닫는 서보 모터를 제어
  • 온도와 습도의 실시간 업데이트
  • 스트리밍 라이브 비디오
  • 스냅샷을 찍어 텔레그램 채팅방에 전송

  • 새집 계기판이 운행하고 있다

    하드웨어


    우리는 프로젝트에서 다음과 같은 하드웨어를 사용할 것이다.
  • 복분자3
  • Raspberry Pi 카메라 V2
  • GPIO 트랙 18 및 GND
  • 에 간단한 LED 연결
  • GPIO 인풋 23, 5V 및 GND
  • 에 연결하는 간단한 서보 모터
  • DHT22 온도/습도 센서 1개, GPIO 트랙 4, 3.3V 및 GND
  • 에 연결
    접지
    3.3V
    5V 전압
    GPIO
    DHT22형
    x
    x
    사.
    서보
    x
    x
    23
    발광 다이오드
    x
    십팔

    새로운 불로약 신경 프로젝트를 세우다


    불로장생의 약 생태계에 대해 내가 진정으로 좋아하는 것은 네가 필요로 하는 대부분 좋은 기록이 있다는 것이다.
    Mac, Linux 또는 Windows에서 개발 환경을 설정하려면 공식 설명서를 참조하십시오.https://hexdocs.pm/nerves/installation.html

    우리의 첫 번째 신경 프로젝트를 만들다


    우리는 우리의 응용 프로그램에 "poncho 프로젝트"구조를 사용할 것입니다. 따라서 우리는 그것을 몇 개의 작은 응용 프로그램으로 나누고, 이 응용 프로그램들은 모노포에서 생활할 것입니다.
    너는 공식 사이트에서 우피 프로젝트의 설정을 찾을 수 있다. https://hexdocs.pm/nerves/user-interfaces.html
    안내서를 따를 때 저희 --live 를 잊지 말고 --no-webpack 속성을 생략하십시오.
    mix phx.new bird_app_ui --no-ecto --live
    
    

    SSH를 통한 WiFi 설정 및 업데이트


    Neurs는 SSH 설정을 통해 업데이트하는 간단한 방법을 제공하기 때문에 SD카드를 개발 장치에서raspberrypi로 자주 교환할 필요가 없습니다.

    WiFi 구성 업데이트


    우선 SSID 및 PSK에 환경 변수를 사용할 수 있도록 WiFi 구성을 업데이트합니다.
    # bird_app_firmware/config/target.exs
    
    # ...
    # Configure the network using vintage_net
    # See <https://github.com/nerves-networking/vintage_net> for more information
    config :vintage_net,
      regulatory_domain: "US",
      config: [
        {"usb0", %{type: VintageNetDirect}},
        {"eth0",
         %{
           type: VintageNetEthernet,
           ipv4: %{method: :dhcp}
         }},
         {"wlan0",
         %{
           type: VintageNetWiFi,
           vintage_net_wifi: %{
             key_mgmt: :wpa_psk,
             ssid: System.get_env("NERVES_NETWORK_SSID"),
             psk: System.get_env("NERVES_NETWORK_PSK")
           },
           ipv4: %{method: :dhcp}
         }}
      ]
    # ...
    
    환경 변수를 설정하려면 터미널에서 다음 명령을 수행합니다.
    export MIX_TARGET=rpi3
    export MIX_ENV=dev
    export NERVES_NETWORK_SSID=your_wifi_name
    export NERVES_NETWORK_PSK=your_wifi_password
    

    SSH 배포 보기


    이제 혼합 의존 항목 목록에 nerves_firmware_ssh 패키지를 추가할 수 있습니다
    # bird_app_firmware/mix.exs
    
    # ...
      defp deps do
        [
          # Dependencies for all targets
          {:nerves_firmware_ssh, "~> 0.3", targets: @all_targets},
          {:bird_app_ui, path: "../bird_app_ui"},
          {:nerves, "~> 1.6.0", runtime: false},
          # ...
        ]
      end
    # ...
    
    지금 cd 너의 bird_app_firmware 달리기에 들어간다
    mix deps.get
    mix firmware
    # (Connect the SD card)
    mix firmware.burn
    
    지금부터 SD카드를 라즈베리에 삽입한 후 ssh nerves.local 라즈베리 pi에 접근하여 디버깅을 할 수 있고, bird_app_firmware 업데이트를 배치할 수 있습니다
    # create new firmware
    mix firmware
    # upload firmware via ssh
    mix upload
    

    Picam - 비디오 스트림 설정


    프로젝트에서 Pi NoIR Camera V2 모듈을 사용합니다.
    Buy a Pi NoIR Camera V2 - Raspberry Pi

    기본 picam 설정


    불로장생약 시력 / 피카무


    Elixir 라이브러리는 카메라 모듈을 사용하여 라즈베리 원주율에서 MJPEG 영상을 포착하는 데 사용된다.


    피카무



    Picam은 Elixir 라이브러리로 간단한 API를 제공하여 Linux를 실행하는 Raspberry Pi 장치에서 카메라 모듈을 사용하여 MJPEG 영상을 유동적으로 전송하고 JPEG 영상을 포착하는 데 사용된다.
    API가 현재 지원하는 기능:
  • 예도, 명암비, 밝기, 포화도, ISO 및 셔터 속도 값 설정
  • 노출, 센서, 측광 및 백색 균형 모드 설정
  • 이미지 및 색상 효과 설정
  • 수직 및 수평 회전 및 뒤집기 이미지
  • 노출 보상(EV) 수준 설정
  • 이미지 크기 변경
  • 품질 수준, 재부팅 간격 및 관심 영역을 통해 JPEG 보증 조정
  • 비디오 안정성 활성화 또는 비활성화
  • 비디오 프레임 속도 조정
  • 전체 화면 또는 창 비디오 미리보기를 HDMI 및 CSI 모니터로 렌더링
  • 위의 기능에 대한 자세한 내용은 Hex docs 을 참조하십시오.

    요구 사항


    요구 사항
    메모
    호스트 장치
    크랜베리 껍질 1, 2, 3, 0/W
    0과 0W는 aspecial ribbon cable가 필요합니다.
    운영 체제
    Linux
    상자를 열면 바로 사용할 수 있다.

    View on GitHub
    우선, 우리의bird_ 응용 프로그램 폴더에 새 프로젝트를 만들 것입니다.
    실행 mix new bird_app_hardware --sup 주관자와 새로운 혼합 프로젝트를 만들고picam을 의존항 목록에 추가합니다.
    # bird_app_hardware/mix.exs
    
    # ...
      defp deps do
        [
          {:picam, "~> 0.4.0"}
        ]
      end
    # ..
    
    개발 중에 FakeCamera를 사용할 수 있도록 구성을 업데이트bird_app_hardware합니다.
    # bird_app_hardware/config/confix.exs
    
    use Mix.Config
    
    config :picam, camera: Picam.FakeCamera
    
    config :logger,
      level: :debug,
      utc_log: true
    
    config :logger, :console,
      level: :debug,
      format: "$dateT$time [$level] $message\\n"
    
    bird_app_hardware/lib/bird_app_hardwarecamera.ex 라는 두 개의 새 파일 만들기
    # bird_app_hardware/lib/bird_app_hardware/camera.ex
    
    defmodule BirdAppHardware.Camera do
        use GenServer
        alias BirdAppHardware.Configuration
        require Logger
    
        def get_config(), do: GenServer.call(__MODULE__, :get_config)
    
        def set_size(width, height) do
          GenServer.call(__MODULE__, {:set_size, width, height})
        end
    
        def set_img_effect(effect) do
          GenServer.call(__MODULE__, {:set_img_effect, effect})
        end
    
        defdelegate next_frame(), to: Picam
    
        def start_link(opts \\\\ []) do
          GenServer.start_link(__MODULE__, opts, name: __MODULE__)
        end
    
        def init(_opts) do
          Logger.info("Configuring camera")
          conf = %Configuration{}
          Picam.set_size(conf.size.width, conf.size.height)
          Picam.set_img_effect(conf.img_effect)
          {:ok, conf}
        end
    
        def handle_call(:get_config, _from, conf), do: {:reply, conf, conf}
    
        def handle_call({:set_size, width, height}, _from, conf) do
          case Picam.set_size(width, height) do
            :ok ->
              if width > 1280 do
                Picam.set_quality(5)
              else
                Picam.set_quality(15)
              end
    
              conf = %{conf | size: %{width: width, height: height}}
              {:reply, :ok, conf}
    
            err ->
              {:reply, err, conf}
          end
        end
    
        def handle_call({:set_img_effect, effect}, _from, conf) do
          case Picam.set_img_effect(effect) do
            :ok ->
              conf = %{conf | img_effect: effect}
              {:reply, :ok, conf}
    
            err ->
              {:reply, err, conf}
          end
        end
    end
    
    # bird_app_hardware/lib/bird_app_hardware/configuration.ex
    
    defmodule BirdAppHardware.Configuration do
      defstruct size: %{width: 640, height: 480},
                img_effect: :normal
    
      @typedoc @moduledoc
      @type t ::
              %__MODULE__{
                size: dimensions(),
                img_effect: img_effect()
              }
    
      @type dimensions ::
              %{width: non_neg_integer(), height: non_neg_integer()}
    
      @type img_effect ::
              :normal
              | :sketch
              | :oilpaint
    end
    
    현재, 우리는 configuration.ex.에서picam 어린이를 우리의 주관자에게 추가할 수 있다.
    # bird_app_hardware/lib/bird_app_hardware/application.ex
    
    # ...
    def start(_type, _args) do
        children = [
          # Starts a worker by calling: BirdAppHardware.Worker.start_link(arg)
          # {BirdAppHardware.Worker, arg}
          Picam.Camera,
          BirdAppHardware.Camera
        ]
    # ...
    
    마지막으로 application.ex 항목을 bird_app_hardware bird_app_firmware 파일 의존 항목에 추가합니다.
    # bird_app_firmware/mix.exs
    
    # ...
      defp deps do
        [
          # Dependencies for all targets
          {:bird_app_hardware, path: "../bird_app_hardware"},
          # ...
        ]
      end
    # ...
    

    JPG 흐름 구축


    우리는picam의 공공 흐름을 원하기 때문에, 우리의mix.exs에 포함하고, 케이블 모듈을 만듭니다.
    # bird_app_ui/lib/bird_app_ui_web/streamer.ex
    
    defmodule BirdAppUi.Streamer do
      @moduledoc """
      Plug for streaming an image
      """
      import Plug.Conn
    
      @behaviour Plug
      @boundary "w58EW1cEpjzydSCq"
    
      def init(opts), do: opts
    
      def call(conn, _opts) do
        conn
        |> put_resp_header("Age", "0")
        |> put_resp_header("Cache-Control", "no-cache, private")
        |> put_resp_header("Pragma", "no-cache")
        |> put_resp_header("Content-Type", "multipart/x-mixed-replace; boundary=#{@boundary}")
        |> send_chunked(200)
        |> send_pictures
      end
    
      defp send_pictures(conn) do
        send_picture(conn)
        send_pictures(conn)
      end
    
      defp send_picture(conn) do
        jpg = BirdAppHardware.Camera.next_frame
        size = byte_size(jpg)
        header = "------#{@boundary}\\r\\nContent-Type: image/jpeg\\r\\nContent-length: #{size}\\r\\n\\r\\n"
        footer = "\\r\\n"
        with {:ok, conn} <- chunk(conn, header),
             {:ok, conn} <- chunk(conn, jpg),
             {:ok, conn} <- chunk(conn, footer),
          do: conn
      end
    end
    
    다음 내용을 우리의 bird_app_ui 에 추가합니다.
    # bird_app_ui/lib/bird_app_ui_web/router.ex
    
    # ...
    forward "/video.mjpg", BirdAppUi.Streamer
    
    펌웨어 cd를 router.ex로 업데이트하고 실행bird_app_firmware & & mix firmware.
    지금 방문할 수 있을 것입니다mix upload.그래도 문제가 있어요.60초 후에 표준 설정으로 인해 우리는 시간 초과를 만났다.이 문제를 해결하기 위해서 우리는 nerves.local/video.mjpeg 을 무한대로 바꿔야 한다.
    # bird_app_firmware/config/target.exs
    
    use Mix.Config
    
    # When we deploy to a device, we use the "prod" configuration:
    import_config "../../bird_app_ui/config/config.exs"
    import_config "../../bird_app_ui/config/prod.exs"
    
    config :bird_app_ui, BirdAppUiWeb.Endpoint,
      # Nerves root filesystem is read-only, so disable the code reloader
      code_reloader: false,
      http: [
        port: 80,
        protocol_options: [
          idle_timeout: :infinity
        ]
      ],
      # Use compile-time Mix config instead of runtime environment variables
      load_from_system_env: false,
      # Start the server since we're running in a release instead of through `mix`
      server: true,
      url: [host: "nerves.local", port: 80]
    #...
    
    지금, 우리는 완벽한 연속 생방송이 우리의picam에서 흘러나오고 있다.

    단일 이미지에 스냅샷 플러그인 추가


    비디오의 단일 이미지에 경로를 쉽게 추가하기 위해 idle_timeout 기능을 이용한 플러그인을 추가할 수 있습니다
    # bird_app_ui/lib/bird_app_ui_web/snap_plug.ex
    
    defmodule BirdAppUiWeb.SnapPlug do
      import Plug.Conn
    
      def init(opts), do: opts
      def call(conn, _opts) do
        conn
        |> put_resp_header("Age", "0")
        |> put_resp_header("Cache-Control", "no-cache, private")
        |> put_resp_header("Pragma", "no-cache")
        |> put_resp_header("Content-Type", "image/jpeg")
        |> send_resp(200, BirdAppHardware.Camera.next_frame())
      end
    
    end
    
    한 노선next_frame()을 전달합니다.
    # bird_app_ui/lib/bird_app_ui_web/router.ex
    
    # ...
    forward "/snap.jpg", BirdAppUiWeb.SnapPlug
    # ...
    

    온도 및 습도 센서용 LiveView 구성 요소


    저는 DHT22를 온도/습도 센서로 사용하여 GPIO 4 인풋 및 다음 6각 패키지에 연결합니다.

    회사 명 / dht 회사


    Elixir는 DHT11 및 DHT22 센서 읽기 가능


    DHT 회사


    DHT 11, DHT 22 및 AM2302 온도/습도 센서 드라이브

    설치


    포트 연결Adafruit Python DHT 라이브러리
    pin 읽기를 처리하기 위한 C 소스 코드입니다.
    현재 이것은 효과적인 신경 목표만 지원하지만, 미래에는 사용할 수 있을 것이다
    GPIO가 있는 불로장생약 환경에서 사용(예를 들어rasbian).
    지원되지 않는 플랫폼(예: 호스트, MacOS 등)의 경우 읽기 수는 유효하지만
    무작위 생성.
    def deps() do
      {:dht, "~> 0.1"}
    end

    See the datasheets for more info:

    활용단어참조

    You need to specify the GPIO pin number and sensor type when taking a reading The sensor type can be a string, atom, or integer representation of the target sensor:

    iex()> DHT.read(6, :dht22)
    {:ok, %{temperature: 22.6, humidity: 50.5}}
    iex()> DHT.

    Add dht to your list of dependencies.

    # bird_app_hardware/mix.exs
    
    # ...
      defp deps do
        [
          {:dht, "~> 0.1"}
        ]
      end
    # ..
    
    GenServer를 다시 사용할 것입니다. GenServer가 초기화되면 2초 간격으로 /snap.jpg으로 데이터 조회를 시작하고 원격 이벤트를 사용할 수 있습니다.
    # bird_app_hardware/lib/bird_app_hardware/dht.ex
    
    defmodule BirdAppHardware.Dht do
      use GenServer
      require Logger
    
      @dht_pin Application.get_env(:bird_app_hardware, :dht_pin, 4)
    
      def start_link(state \\ []) do
        GenServer.start_link(__MODULE__, state, name: __MODULE__)
      end
    
      def init(_state) do
        Logger.info("Starting DHT Sensor")
        DHT.start_polling(@dht_pin, :dht22, 2)
        {:ok, %{temperature: "Loading...", humidity: "Loading..."}}
      end
    
      def read() do
        GenServer.call(__MODULE__, :read)
      end
    
      def handle_call(:read, _from, state) do
        {:reply, state, state}
      end
    
      def handle_cast({:update, measurements}, _state) do
        {:noreply,
         %{
           humidity: floor(measurements.humidity),
           temperature: floor(measurements.temperature)
         }}
      end
    
      def handle_event(_event, measurements, _metadata, _config) do
        GenServer.cast(__MODULE__, {:update, measurements})
        |> broadcast(:dht_update, %{
          humidity: floor(measurements.humidity),
          temperature: floor(measurements.temperature)
        })
      end
    
      def subscribe do
        Phoenix.PubSub.subscribe(BirdAppUi.PubSub, "dht")
      end
    
      defp broadcast(:ok, event, data) do
        Phoenix.PubSub.broadcast(BirdAppUi.PubSub, "dht", {event, data})
        {:ok, data}
      end
    end
    
    # bird_app_ui/lib/bird_app_ui/application.ex
    
    # ...
    :telemetry.attach("dht", [:dht, :read], &BirdAppHardware.Dht.handle_event/4, nil)
    # ...
    
    이제 LiveComponent를 만듭니다. LiveView에 살고 연결을 맺은 후 바로 이 이벤트에 가입합니다.
    그런 다음 LiveView는 브로드캐스트를 처리하고 각 LiveComponent에 업데이트를 전송합니다.
    # bird_app_ui/lib/bird_app_ui_web/live/components/stats_component.ex
    
    defmodule BirdAppUiWeb.StatsComponent do
      use BirdAppUiWeb, :live_component
    
      @impl true
      def mount(socket) do
        {:ok, socket}
      end
    
      @impl true
      def update(assigns, socket) do
        {:ok, assign(socket, assigns)}
      end
    
      @impl true
      def render(assigns) do
        ~L"""
        <div class="w-full md:w-1/3 p-3">
          <div class="rounded shadow-lg p-2">
              <div class="flex flex-row items-center">
                  <div class="flex-shrink pr-4">
                      <!-- empty div so bg-colors don't get purged while we load the css class from the @color variable -->
                      <div class="bg-green-600 bg-blue-600 bg-orange-600 hidden"></div>
    
                      <div class="rounded p-3 bg-<%= @color %>-600"><i class="fa <%= @icon %> fa-2x fa-fw fa-inverse"></i></div>
                  </div>
                  <div class="flex-1 text-right md:text-center">
                      <h5 class="font-bold uppercase text-gray-400"><%= @stats_name %></h5>
                      <h3 class="font-bold text-3xl text-gray-600"><%= @stats %><%= @character %></h3>
                  </div>
              </div>
          </div>
        </div>
        """
      end
    end
    
    
    # bird_app_ui/lib/bird_app_ui_web/live/page_live.ex
    
    # ...
      @impl true
      def mount(_params, _session, socket) do
        if connected?(socket), do: BirdAppHardware.Dht.subscribe()
    
        measurements = BirdAppHardware.Dht.read()
    
        {:ok,
         assign(socket,
           temperature: measurements.temperature,
           humidity: measurements.humidity
         )}
      end
    
      @impl true
      def handle_info({:dht_update, measurements}, socket) do
        send_update(BirdAppUiWeb.StatsComponent, id: "humidity", stats: measurements.humidity)
        send_update(BirdAppUiWeb.StatsComponent, id: "temperature", stats: measurements.temperature)
        {:noreply, socket}
      end
    # ...
    
    
    # bird_app_ui/lib/bird_app_ui_web/live/page_live.html.leex
    
    # ...
    <%= live_component @socket, BirdAppUiWeb.StatsComponent, id: "temperature", stats: @temperature, stats_name: "Temperature", color: "orange", icon: "fa-thermometer-half", character: "°C" %>
    <%= live_component @socket, BirdAppUiWeb.StatsComponent, id: "humidity", stats: @humidity, stats_name: "Humidity", color: "blue", icon: "fa-tint", character: "%" %>
    # ...
    
    이 프로젝트에서 Tailwind-CSS를 사용했음을 알 수 있습니다.elixir 프로젝트에서 Tailwind CSS를 설정하는 방법에 관심이 있으시면 https://andrich.me/learn-elixir-and-phoenix-add-tailwind-css

    텔레그램 채팅으로 스냅샷 보내기


    만약 네가 공교롭게도 새 한 마리가 시냇물 속에서 생활하는 것을 보았다면, 이 순간을 붙잡는 것이 가장 좋다.응용 프로그램에서 간단한 전신 로봇을 어떻게 실현하는지 보여 드리겠습니다.
    나는nadiatelegrambothex패키지를 사용할 것이다.

    활용단어참조 / 나디아


    Elixir로 작성된 텔레 로봇 API 패키지


    나디아


    Elixir(document로 작성된 텔레 로봇 API 패키지

    설치


    Nadia를 의존 항목DHT.start_polling(4, :dht22, 2)에 추가합니다.
    def deps do
      [{:nadia, "~> 0.7.0"}]
    end

    and run $ mix deps.get.

    프로비저닝

    In config/config.exs, add your Telegram Bot token like this

    config :nadia
      token: "bot token"

    You can also add an optional recv_timeout in seconds (defaults to 5s).

    config :nadia,
      recv_timeout: 10

    You can also add a proxy support.

    config :nadia,
      proxy: "http://proxy_host:proxy_port", # or {:socks5, 'proxy_host', proxy_port}
      proxy_auth: {"user", "password"},
      ssl: [versions: [:'tlsv1.2']]

    You can also configure the the base url for the api if you need to for some reason.

    config :nadia,
      # Telegram API. Default: https://api.telegram.org/bot
      base_url: "http://my-own-endpoint.com/whatever/",
    
      # Telegram Graph API. Default: https://api.telegra.ph
      graph_base_url: "http://my-own-endpoint.com/whatever/"

    Environment…

    First install the necessary dependencies

    # bird_app_ui/mix.exs
    
    # ...
    {:nadia, "~> 0.7.0"}
    # ...
    
    config/config에서exs, 이렇게 전신 로봇 영패 추가
    # bird_app_ui/config/config.exs
    
    # ...
    config :nadia,
      token: System.get_env("TELEGRAM_BOT_TOKEN"),
      chat_id: System.get_env("TELEGRAM_CHAT_ID")
    # ...
    
    이제 새 LiveComponent를 만듭니다.
    # bird_app_ui/lib/bird_app_ui_web/live/telegram_snap_component.ex
    
    defmodule BirdAppUiWeb.TelegramSnapComponent do
      use BirdAppUiWeb, :live_component
    
      alias BirdAppHardware.Camera
    
      @chat_id Application.get_env(:nadia, :chat_id)
    
      @impl true
      def mount(socket) do
        {:ok, socket}
      end
    
      @impl true
      def render(assigns) do
        ~L"""
        <button class="w-full font-bold bg-white hover:bg-gray-100 text-gray-800 py-2 px-4 border border-gray-400 rounded shadow my-2" phx-click="snap" phx-target="<%= @myself %>">
          Snap
        </button>
        """
      end
    
      @impl true
      def handle_event("snap", _, socket) do
        File.write!("/tmp/snap.jpg", Camera.next_frame())
        Nadia.send_photo(@chat_id, "/tmp/snap.jpg")
        {:noreply, socket}
      end
    end
    
    
    # bird_app_ui/lib/bird_app_ui_web/live/page_live.html.leex
    
    # ...
    <%= live_component @socket, BirdAppUiWeb.TeleGramSnapComponent, id: "telegram-snap" %>
    # ...
    
    단추를 눌렀을 때, 구성 요소는 mix.exs 이벤트를 자신에게 보냅니다. 우리는 먼저 임시 snap 파일에 snap.jpg 의 내용을 포함하고, 최종적으로 그것을 전보로 보낼 수 있습니다.

    마지막 한마디


    솔직히 말하면, 나는 Elixir로 물건을 개발하고 구축하는 데 많은 즐거움을 가지고 있으며, 미래에는 더 많이 할 것이다.
    내 명세서에는 실시간 조류 검출 같은 임무가 있다.우리는 또한 모든 내용을 아래의 물리적 새집에 실현하고 3d로 추가 자산, 예를 들어picam 브래킷과 음식 용기를 인쇄해야 한다.

    나는 모든 구성 요소를 상세하게 소개하지 않았다.응용 프로그램 개발에 관심이 있다면 git repository 을 보고 사용해 보세요!

    불로장생약, 신경, 봉황대 덕분에💫


    나의 학습 자원

  • 불로장생약에 대한 멋진 소개: https://joyofelixir.com/
  • 더 자세한 소개와 좋은 책 https://www.manning.com/books/elixir-in-action-second-edition
  • Phoenix LiveView 알기 쉬운 튜토리얼https://pragmaticstudio.com/courses/phoenix-liveview
  • Greg Meffords omni_eye 응용 프로그램, 바코드와 흐르는 미디어 영상을 스캔하는 데 사용되며, 나는 그 중에서 MJPG 흐르는 미디어 코드를 얻었다https://github.com/GregMefford/omni_eye/tree/master
  • 화면 방송https://elixircasts.io/
  • 좋은 웹페이지 즐겨찾기