E-Ink, Python, IoT로 다양한 콘텐츠를 제공하는 블로그

2007년 뉴욕타임스는 마크 핸슨(Mark Hansen)과 벤 루빈(Ben Rubin)이라는 이동식 예술 장치를 기획했다.마크와 벤은 이 신문의 150여 년 역사 파일에서 톱기사와 인용문을 뽑아 빌딩 로비의 560개의 작은 스크린에 보여 주었다.2014년 처음 전시회를 관람한 후 타임스퀘어를 지나갈 때마다 나는 특별히 참관하러 갔다.

리·루빈 촬영
2019년에 나는 한 협력자Marty Chafkin from Perfection Electricks가 브루클린 연구원의 프로젝트에 대해 이야기하는 것을 들을 기회가 있었다.그는 데이터 수집 과정과 그들이 어떻게 데이터를 뉴욕타임스 파일에서 꺼내 모든 장치에 넣는지 언급했지만, 화면을 업데이트하는 간단한 방법은 없었다.나는 또 화면에서 인용된 문장을 찾기가 매우 어렵다는 것을 알아차렸다.
그때 나는 "와, 만족은 좋은 용례가 될 거야."라고 생각했다.그러나 당시에는 저소모 스크린이 없었고 단기간 내에 참여할 기회가 없는 프로젝트인 줄 알았다.
지난해 말 뉴욕에 본사를 두고 있는 오픈소스 하드웨어 회사인 아다프루트Adafruit MagTag가 전자제품을 배우는 데 도움을 주는 제품을 개발했다.MagTag은 ESP32-S2 무선 모듈이 결합된 2.9형 전자 잉크 디스플레이다.Python으로 코드를 작성할 수 있는 저전력 사물인터넷 디스플레이다.그것은 네 개의 내장된 컬러 미니 LED와 네 개의 단추가 있다.
나는 가능한 한 빨리 한 대를 주문해서 이것이 나의 모바일 버전을 다시 제작할 기회가 될 것이라고 결정했다.
MagTag 버튼은 화면에 표시되는 모든 내용의 링크를 포함하여 사용자에게 알림을 보낼 수 있습니다.나는 손을 내밀어 내가 이 마지막 부분을 완성하는 것을 도왔다.아드리안과 나는 2020년 11월에 Courier API 디자인과 알림 발송을 어떻게 사용하는지 공유했다.그는 Discord를 통해 콘텐츠를 공유하자고 제안했는데, 다행히도 저와 자유롭게 온라인으로 프로젝트를 구축할 수 있었다.

코드 보여주세요.


만약 당신이 완전한 코드를 보고 싶다면 GitHub에 가도 됩니다.
내가 MagTag을 이렇게 좋아하는 이유 중 하나는 Python을 지원하기 때문이다.Circuit Python은 Python의 버전으로 표준 Python에 하드웨어 지원을 추가합니다.전통적인 Python 프로젝트와 달리 드래그를 통해 의존 항목을 설치할 수 있습니다.mpy 파일은 pip 같은 패키지 관리자를 사용하지 않고 마이크로 컨트롤러의 메인보드에 설치되어 있습니다.대부분의 IoT 회로판에 메모리가 많지 않기 때문에, 내용이 풍부한 파이톤 SDK를 새로운 프로그램으로 컴파일하고 싶지 않다.mpy 파일 - HTTP를 통해 컨텐츠가 있는 API에 액세스하도록 선택했습니다.

Adafruit는 사전 컴파일된 몇 가지를 제공합니다.mpy 파일은 Python에서 가장 유용한 라이브러리입니다.Adafruit 버전의 요청은 사전 컴파일되었으므로 사용할 것입니다.mpy 파일.먼저 필요한 모든 종속성을 가져오고 환경 변수를 가져와 WiFi에 연결합니다.
import time
import gc
import wifi
import random
import adafruit_requests
import ssl
import socketpool
import terminalio
from adafruit_magtag.magtag import MagTag

magtag = MagTag()

# Add a secrets.py to your filesystem that has a dictionary called secrets with "ssid" and
# "password" keys with your WiFi credentials. DO NOT share that file or commit it into Git or other
# source control.
# pylint: disable=no-name-in-module,wrong-import-order
try:
    from secrets import secrets
except ImportError:
    print("Credentials and tokens are kept in secrets.py, please add them there!")
    raise

print("Connecting to %s" % secrets["ssid"])
wifi.radio.connect(secrets["ssid"], secrets["password"])
print("Connected to %s!" % secrets["ssid"])

pool = socketpool.SocketPool(wifi.radio)
requests = adafruit_requests.Session(pool, ssl.create_default_context())
다행히도 제last post는 HTTP를 통해GraphQL을 사용하는 것에 관한 것입니다.나는 생산 내용 블로그의 서로 다른 조회와 API 키를 고려하여 이전의 파이톤 코드를 다시 사용했다.기존의 Contentful Rest API 대신 우리GraphQL API를 사용하는 장점은 내가 Contentful API에 대한 호출 수량을 줄이고 응답의 유효 부하를 줄이는 것이다.

컨텐트 가져오기


우선 콘텐츠풀에 전화를 걸어 마지막 100편의 블로그를 받습니다.com/blog.
endpoint = "https://graphql.contentful.com/content/v1/spaces/%s/" % (
    secrets["space_id"]
)
headers = {"Authorization": "Bearer %s" % (secrets["CDA_token"])}

# Get Dev Blog Posts
query = """query {
  blogPostCollection {
    items {
      sys {
        id
      }
    }
  }
}
"""

print("Making blog post collection query.")
response = requests.post(endpoint, json={"query": query}, headers=headers)
다음은 랜덤으로 블로그 글 중 한 편을 선택하여 전자 잉크 화면에 글을 표시하는 데 필요한 모든 정보를 얻습니다.메모리는 하나의 제약이기 때문에, 새로운 변수를 설정하는 것이 아니라 이전에 사용했던 조회와 요청을 덮어씁니다.
# Get Individual Post
query = """{
  blogPost(id: \"%s\") {
    title
    publishDate
    slug
    authorsCollection {
      items {
        name
      }
    }
    introduction
  }
}
""" % (
    random.choice(response.json()["data"]["blogPostCollection"]["items"])["sys"]["id"]
)

print("Making blog post query.")
response = requests.post(endpoint, json={"query": query}, headers=headers)
이 요청이 있으면 모든 내용을 인간이 읽을 수 있는 형식으로 해석하여 화면에 표시할 수 있습니다.화면 자체가 2.9인치에 불과하기 때문에, 우리는 블로그 게시물마다 170글자만 사용할 것이다.
MagTag에는 텍스트 상자를 만들고 설정하는 기능이 있습니다.상자가 준비되면, 우리는 텍스트를 설정하고, 화면에 새로 고침이 필요한지 알 수 있습니다.화면에 표시된 항목마다 네 개의 텍스트 상자를 편집하고 있기 때문에, 최종 텍스트 항목이 설정될 때까지 리셋 이벤트를 미룰 수 있습니다.
# Formatting for the author text
magtag.add_text(
    text_font="/fonts/Arial-Bold-12.pcf",
    text_position=(10, 38),
)

author_string = ""
for author in response.json()["data"]["blogPost"]["authorsCollection"]["items"]:
    if author_string == "":
        author_string = author["name"]
    else:
        author_string = author_string + " & " + author["name"]

magtag.set_text(
    val=author_string,
    index=1,
    auto_refresh=False,
)
이 세션에서, 나는 author 필드에 텍스트 상자를 만들었다.다음에 나는 우리 작가를 위해 문자열을 만들어서 작가 그룹에서 순환시켰다. 왜냐하면 블로그 글에 여러 명의 작가가 있을 수 있기 때문이다.마지막으로, 나는 생성된 문자열로 텍스트 상자를 설정합니다.이것은 우리가 변경해야 할 네 개의 텍스트 상자 중 두 번째이기 때문에, 디스플레이를 업데이트하지 말라고 알려 줍니다.전체 디스플레이 코드를 보려면 GitHub로 이동합니다.

Courier API에 메시지 보내기


사용자가 MagTag 단추를 눌렀을 때, 나는 그들에게 완전한 글의 링크를 보내고 싶다.아드리안은 이 목표를 실현하는 데 매우 중요하다는 사실이 증명되었다.그는 HTTP 요청을 통해 공지를 보낼 수 있는 Courier API 기능을 이용할 수 있다고 말했다.
이전과 같이, 우리는 이전에 사용한 변수를 덮어쓰고 요청을 보냅니다.글의 정보를 공유하기 때문에 요청 본문에 포함시켜 주십시오.우리는 사절로부터 온 정보를 사용하여 잠시 후의 통지를 설계할 수 있다.마지막으로 이벤트를 설정해야 합니다.Courier는 이 정보를 사용하여 특정 정보의 구체적인 상황을 확인합니다.
endpoint = "https://api.courier.com/send/"
headers["Authorization"] = "Bearer %s" % (secrets["courier_token"])
headers["Accept"] = "application/json"
headers["Content-Type"] = "application/json"

courier_JSON = {
    "event": "MAGTAG_NOTIFICATION",
    "recipient": "discord_channel",
    "data": {
        "title": response.json()["data"]["blogPost"]["title"],
        "introduction": response.json()["data"]["blogPost"]["introduction"][0:170]
        + "...",
        "url": blog_url,
        "author": author_string,
        "publish_date": strdate,
    },
}
다음에 우리는 순환을 설정하고 감청 단추를 누르기 시작합니다.버튼을 누르면 회로판이 무엇을 하고 있는지 피드백하는 색을 보여 줍니다.택배 기사한테 요청해.
print("Starting the loop, go ahead and press some buttons. :)")
while True:
    if magtag.peripherals.button_a_pressed:
        if button_a_pressed == False:
            for i, b in enumerate(magtag.peripherals.buttons):
                magtag.peripherals.neopixel_disable = False
                magtag.peripherals.neopixels[i] = button_colors[i]
                time.sleep(0.25)
                magtag.peripherals.neopixels[i] = (0, 0, 0)
            print("Making request to Courier")
            response = requests.post(endpoint, json=courier_JSON, headers=headers)
            button_a_pressed = True
            print("Courier response: ")
            print(response.json())

    if magtag.peripherals.button_d_pressed:
        for i, b in enumerate(magtag.peripherals.buttons):
            magtag.peripherals.neopixel_disable = False
            magtag.peripherals.neopixels[i] = button_colors[i]
            time.sleep(0.25)
            magtag.peripherals.neopixels[i] = (0, 0, 0)
            # magtag.peripherals.play_tone(button_tones[i], 0.25)
    else:
        button_a_pressed = False
        magtag.peripherals.neopixel_disable = True
pass
버튼을 클릭하여 회로판을 켜고 첫 번째 요청을 보냅니다!

Courier 구성


Courier는 Discord, SendGrid, Twilio를 비롯한 다양한 알림 흐름을 지원합니다.Courier 웹 사이트에서 클릭하여 설명에 따라 통합 플랫폼에 연결합니다(제 예에서 Discord를 선택했습니다).이 예제에서 선택한 특정 통합은 중요하지 않지만 사용하려는 서비스의 API 키를 제공해야 합니다.

다음에 새 알림을 만듭니다.이사회에 먼저 요청을 했기 때문에 통지를 설정할 때 이 요청의 기록을 사용할 수 있습니다.

이전에 사용했던 통합 플랫폼을 선택하고 채널에 추가합니다.여기서 알림을 보낼 때의 외관을 디자인할 수 있습니다.JSON 요청에서 글의 정보를 전달했기 때문에 알림 디자인에서 이 데이터를 사용할 수 있습니다.

Courier dashboard에서 요약하려면 데이터 탭을 가리키고 MagTag의 POST 요청에서 설정한 이벤트와 일치하는 레코드 중 하나를 클릭하십시오.이 때 요청은 이와 관련된 알림이 없기 때문에 Map to Notifications를 누르고 방금 설계한 알림을 선택할 수 있습니다.

기록을 테스트 이벤트로 저장하고 알림 디자이너로 되돌려줍니다.디자인한 알림의 미리 보기를 누르면 Courier는 이 기록을 사용하여 알림을 보낼 때의 외관을 표시합니다.

마지막으로 MagTag으로 돌아가서 버튼을 눌러서 요청을 하세요.MagTag은 Courier에 전화하고 Courier는 요청을 처리하며 연결된 통합 플랫폼에 알림을 보냅니다.

이것이 바로 MagTag이 화면에 내용을 표시하는 데 필요한 모든 것입니다. 사용자가 단추를 누르면 전체 URL에 대한 링크를 보냅니다.

MagTag이 있는 경우 종속성, 내보낸 내용 모델, Courier를 설정하는 방법, 장치에 Courier를 설치하는 방법, 설명서가 포함된 전체 소스 코드 링크를 가져오십시오.이어서 우리 수석재무관을 설득해서 559개의MagTags를 주문할 것이다. 그러면 우리가 만족하는 moveable type으로 베를린 사무실의 로비를 덮을 수 있다.그 전에 내 라벨을 냉장고에 붙일 거야!

좋은 웹페이지 즐겨찾기