<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Hirobon</title><link>http://blog.hirobon1690.com/</link><description>Recent content on Hirobon</description><generator>Hugo -- gohugo.io</generator><language>ja-jp</language><lastBuildDate>Wed, 31 Dec 2025 20:45:00 +0900</lastBuildDate><atom:link href="http://blog.hirobon1690.com/index.xml" rel="self" type="application/rss+xml"/><item><title>2025 今年買ってよかったもの &amp; 買わなくてもよかったもの</title><link>http://blog.hirobon1690.com/post/best-buy-2025/</link><pubDate>Wed, 31 Dec 2025 20:45:00 +0900</pubDate><guid>http://blog.hirobon1690.com/post/best-buy-2025/</guid><description>&lt;img src="http://blog.hirobon1690.com/post/best-buy-2025/thumb.png" alt="Featured image of post 2025 今年買ってよかったもの &amp; 買わなくてもよかったもの" />&lt;h2 id="今年買ってよかったもの">今年買ってよかったもの&lt;/h2>
&lt;p>もう1年が経ってしまった&amp;hellip;&lt;br>
技術的な記事も出したかったのですが，まずは恒例にしていきたいこの記事ってことで．&lt;/p>
&lt;h3 id="topre-realforce-r3s-テンキーありus配列モデル">Topre Realforce R3S テンキーありUS配列モデル&lt;/h3>
&lt;blockquote class="twitter-tweet">&lt;p lang="ja" dir="ltr">ｱｰｰｰｲｯ！！！！ &lt;a href="https://t.co/mV91zo7bUq">pic.twitter.com/mV91zo7bUq&lt;/a>&lt;/p>&amp;mdash; Hirobon (@hirobon1690) &lt;a href="https://twitter.com/hirobon1690/status/1984538187847634949?ref_src=twsrc%5Etfw">November 1, 2025&lt;/a>&lt;/blockquote> &lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8">&lt;/script>
&lt;p>&lt;a class="link" href="https://www.realforce.co.jp/products/series_master_r3s.html" target="_blank" rel="noopener"
>Realforce R3S&lt;/a>&lt;/p>
&lt;p>ついに沼に入ってしまいました．ともあれ打ち心地が最高．もともとメンブレンが好きだったので，静電容量無接点は高級メンブレンって感じの打ち心地で最高！！良いキーボードは早く買ったほうが1日あたりの単価が下がる（&lt;strong>==実質無料&lt;/strong>）ってことで．&lt;/p>
&lt;h3 id="クリア軸静音スイッチとホットスワップ化ソケット">クリア軸静音スイッチとホットスワップ化ソケット&lt;/h3>
&lt;p>ヨドバシで試し打ちをしていたところ，&lt;a class="link" href="https://www.yodobashi.com/product/100000001009028674/" target="_blank" rel="noopener"
>iKBCのクリア軸&lt;/a> という軸の打ち心地が非常によかった．静音スコスコで弱めのタクタイル感がある感じ．静電容量軸の家心地にも近い．しかし，上記のモデルはヨドバシ限定モデルな上にJIS配列しかラインナップがない．そこでスイッチだけAliexpressで取り寄せて，3年ほど前に買った&lt;a class="link" href="https://x.com/hirobon1690/status/1504998488228044805?s=20" target="_blank" rel="noopener"
>赤軸メカニカル&lt;/a> の軸を交換することにした．&lt;br>
ところが私が持っていた赤軸はホットスワップ対応ではない！&lt;a class="link" href="https://www.google.com/search?q=%E3%83%9B%E3%83%83%E3%83%88%E3%82%B9%E3%83%AF%E3%83%83%E3%83%97%E5%8C%96" target="_blank" rel="noopener"
>調べてみると&lt;/a> あとから力技でキーボードをホットスワップ化する方法があるらしい．幸いはんだ付けには慣れていたため，アリエクで取り寄せてやってみることとした．&lt;/p>
&lt;blockquote class="twitter-tweet">&lt;p lang="ja" dir="ltr">これを&lt;br>こうして&lt;br>こう！ &lt;a href="https://t.co/QJZNXGVyyG">pic.twitter.com/QJZNXGVyyG&lt;/a>&lt;/p>&amp;mdash; Hirobon (@hirobon1690) &lt;a href="https://twitter.com/hirobon1690/status/1992850667078386119?ref_src=twsrc%5Etfw">November 24, 2025&lt;/a>&lt;/blockquote> &lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8">&lt;/script>
&lt;p>使ったホットスワップ化ソケットとスイッチは以下である．&lt;/p>
&lt;p>&lt;img src="http://blog.hirobon1690.com/post/best-buy-2025/2.png"
width="851"
height="692"
srcset="http://blog.hirobon1690.com/post/best-buy-2025/2_hud780d38ab260da0969c4b35ce3c6250e_221267_480x0_resize_box_3.png 480w, http://blog.hirobon1690.com/post/best-buy-2025/2_hud780d38ab260da0969c4b35ce3c6250e_221267_1024x0_resize_box_3.png 1024w"
loading="lazy"
alt="AS6490-2040B"
class="gallery-image"
data-flex-grow="122"
data-flex-basis="295px"
>&lt;/p>
error calling resources.GetRemote: Get &amp;#34;https://www.aliexpress.us/item/3256809074590728.html?gatewayAdapt=jpn2usa4itemAdapt&amp;amp;_randl_shipto=US&amp;#34;: stopped after 10 redirects
&lt;p>&lt;img src="http://blog.hirobon1690.com/post/best-buy-2025/3.png"
width="748"
height="709"
srcset="http://blog.hirobon1690.com/post/best-buy-2025/3_hu6dfc6bd0428a28f4ff26bee0faf32432_467313_480x0_resize_box_3.png 480w, http://blog.hirobon1690.com/post/best-buy-2025/3_hu6dfc6bd0428a28f4ff26bee0faf32432_467313_1024x0_resize_box_3.png 1024w"
loading="lazy"
alt="Kailh Deep Sea Box Silent Switch"
class="gallery-image"
data-flex-grow="105"
data-flex-basis="253px"
>&lt;/p>
error calling resources.GetRemote: Get &amp;#34;https://www.aliexpress.us/item/3256808633267860.html?gatewayAdapt=jpn2usa4itemAdapt&amp;amp;_randl_shipto=US&amp;#34;: stopped after 10 redirects
&lt;p>購入当時は送料・クーポン込みで7,000円程度．&lt;br>
これを機に&lt;a class="link" href="https://www.amazon.co.jp/dp/B0D7Q293KV" target="_blank" rel="noopener"
>Engineerのハンダ吸い取り器&lt;/a> も購入．&lt;br>
結局1万円程度+半日がかかった．&lt;del>安めのキーボードなら買えてしまう金額である．&lt;/del> 打鍵感がかなり上がったので非常に満足．&lt;/p>
&lt;h3 id="エレコム-大型マウスパッド">エレコム 大型マウスパッド&lt;/h3>
&lt;p>&lt;img src="http://blog.hirobon1690.com/post/best-buy-2025/4.png"
width="600"
height="600"
srcset="http://blog.hirobon1690.com/post/best-buy-2025/4_hu4ce6215719df37aa33adab7dac4419f4_47643_480x0_resize_box_3.png 480w, http://blog.hirobon1690.com/post/best-buy-2025/4_hu4ce6215719df37aa33adab7dac4419f4_47643_1024x0_resize_box_3.png 1024w"
loading="lazy"
alt="マウスパッド"
class="gallery-image"
data-flex-grow="100"
data-flex-basis="240px"
>&lt;/p>
&lt;style>
@media (prefers-color-scheme: dark) {
.box{
background-color: #5b5b5b;
}
}
.box{
width: 100%;
max-width: 500px;
height: 100px;
background-color: var(--link-card-background) !important;
color: var(--accent-color);
border-radius: 10px;
overflow: hidden;
display: flex!important;
vertical-align: top!important;
box-shadow: 0 0 5px 1px rgba(0, 0, 0, .2);
}
.box:hover{
opacity: 0.8;
}
.text{
margin: 5px 0 0 10px;
}
.img-class {
width: 100px;
height: 100px!important;
object-fit: cover;
}
.url{
font-size: smaller;
color: lightgray;
margin: 0 0 0 10px;
color: var(--accent-color-darker);
}
.flex{
display: flex;
}
&lt;/style>
&lt;a class='flex' href="https://www.amazon.co.jp/dp/B0DSHSTH31" target="_blank" rel="noopener noreferrer">
&lt;div class='box'>
&lt;img src="http://blog.hirobon1690.com/img/default_huf044c2fbafe082fc6235c0e83e8785d7_957_200x200_fill_q100_h2_box_center_3.webp" class='img-class'>
&lt;div>
&lt;p class='text'>エレコム デスクマット 大型マウスパッド 900mm×430mm&lt;/p>
&lt;p class='url'>https://www.amazon.co.jp/dp/B0DSHSTH31&lt;/p>
&lt;/div>
&lt;/div>
&lt;/a>
&lt;p>&lt;span style="font-size: 300%; font-weight:bold">マウスパッドなんてでかけりゃでかいほどいいですからね！！！！！&lt;/span>&lt;/p>
&lt;p>これらによって出来上がった最高のデスクが研究室にあるのだが，写真を撮り忘れて実家に戻ってきてしまったので割愛．&lt;/p>
&lt;h3 id="ダイソー-詰め替えパックホルダー">ダイソー 詰め替えパックホルダー&lt;/h3>
&lt;p>&lt;img src="http://blog.hirobon1690.com/post/best-buy-2025/5.png"
width="700"
height="525"
srcset="http://blog.hirobon1690.com/post/best-buy-2025/5_hu0ba785df5d13077a5260c2812f901eef_104657_480x0_resize_box_3.png 480w, http://blog.hirobon1690.com/post/best-buy-2025/5_hu0ba785df5d13077a5260c2812f901eef_104657_1024x0_resize_box_3.png 1024w"
loading="lazy"
alt="詰め替えパックホルダー"
class="gallery-image"
data-flex-grow="133"
data-flex-basis="320px"
>&lt;/p>
&lt;p>&lt;a class="link" href="https://www.amazon.co.jp/dp/B092GN9RK1" target="_blank" rel="noopener"
>純正品&lt;/a> だと6倍以上するのでお買い得だった．機能面には問題なかったので，あとは耐久性（だいぶ脆そう）&lt;/p>
&lt;h3 id="オムロン-上腕式血圧計">オムロン 上腕式血圧計&lt;/h3>
&lt;p>&lt;img src="http://blog.hirobon1690.com/post/best-buy-2025/image-2.png"
width="1308"
height="786"
srcset="http://blog.hirobon1690.com/post/best-buy-2025/image-2_huee03326a84b22e1122b1c6d5e6857048_650344_480x0_resize_box_3.png 480w, http://blog.hirobon1690.com/post/best-buy-2025/image-2_huee03326a84b22e1122b1c6d5e6857048_650344_1024x0_resize_box_3.png 1024w"
loading="lazy"
alt="オムロン 上腕式血圧計"
class="gallery-image"
data-flex-grow="166"
data-flex-basis="399px"
>&lt;/p>
&lt;style>
@media (prefers-color-scheme: dark) {
.box{
background-color: #5b5b5b;
}
}
.box{
width: 100%;
max-width: 500px;
height: 100px;
background-color: var(--link-card-background) !important;
color: var(--accent-color);
border-radius: 10px;
overflow: hidden;
display: flex!important;
vertical-align: top!important;
box-shadow: 0 0 5px 1px rgba(0, 0, 0, .2);
}
.box:hover{
opacity: 0.8;
}
.text{
margin: 5px 0 0 10px;
}
.img-class {
width: 100px;
height: 100px!important;
object-fit: cover;
}
.url{
font-size: smaller;
color: lightgray;
margin: 0 0 0 10px;
color: var(--accent-color-darker);
}
.flex{
display: flex;
}
&lt;/style>
&lt;a class='flex' href="https://www.amazon.co.jp/dp/B0DB2HSLFY" target="_blank" rel="noopener noreferrer">
&lt;div class='box'>
&lt;img src="http://blog.hirobon1690.com/img/default_huf044c2fbafe082fc6235c0e83e8785d7_957_200x200_fill_q100_h2_box_center_3.webp" class='img-class'>
&lt;div>
&lt;p class='text'>オムロン 上腕式血圧計 HCR-7004&lt;/p>
&lt;p class='url'>https://www.amazon.co.jp/dp/B0DB2HSLFY&lt;/p>
&lt;/div>
&lt;/div>
&lt;/a>
&lt;p>春の健康診断で高血圧で再検査になってしまったので，攻略するために購入．研究室に置いて毎日測ってます．居室メンバーにも大人気(?)です．&lt;/p>
&lt;h2 id="買っても買わなくてもよかったもの">買っても買わなくてもよかったもの&lt;/h2>
&lt;h3 id="ch9120-network-serial-port-to-ethernet-module">CH9120 Network Serial Port to Ethernet Module&lt;/h3>
&lt;p>&lt;img src="http://blog.hirobon1690.com/post/best-buy-2025/6.png"
width="710"
height="542"
srcset="http://blog.hirobon1690.com/post/best-buy-2025/6_hu0efafc30429346b563e48a94ff9f70d6_188065_480x0_resize_box_3.png 480w, http://blog.hirobon1690.com/post/best-buy-2025/6_hu0efafc30429346b563e48a94ff9f70d6_188065_1024x0_resize_box_3.png 1024w"
loading="lazy"
alt="CH9120"
class="gallery-image"
data-flex-grow="130"
data-flex-basis="314px"
>&lt;br>
error calling resources.GetRemote: Get &amp;#34;https://www.aliexpress.us/item/3256801238194352.html?gatewayAdapt=jpn2usa4itemAdapt&amp;amp;_randl_shipto=US&amp;#34;: stopped after 10 redirects&lt;/p>
&lt;p>UART通信をイーサネットに載せて送受信できるICと周辺回路が一体化したモジュール．アリエクで買った直後に&lt;a class="link" href="https://akizukidenshi.com/catalog/g/g129552/" target="_blank" rel="noopener"
>秋月でもブレークアウトボードの取り扱いが開始&lt;/a> されたことを知ったが，LANポートがついている分こちらの方が使いやすい．&lt;br>
ただ，&lt;strong>ボーレートが自由に選択できない&lt;/strong>という弱点がある．&lt;/p>
&lt;p>&lt;img src="http://blog.hirobon1690.com/post/best-buy-2025/image.png"
width="409"
height="518"
srcset="http://blog.hirobon1690.com/post/best-buy-2025/image_hu9087ff246ece8ddebabef5065ca5a9b2_63159_480x0_resize_box_3.png 480w, http://blog.hirobon1690.com/post/best-buy-2025/image_hu9087ff246ece8ddebabef5065ca5a9b2_63159_1024x0_resize_box_3.png 1024w"
loading="lazy"
alt="ボーレートの選択肢"
class="gallery-image"
data-flex-grow="78"
data-flex-basis="189px"
>&lt;/p>
&lt;p>引用：&lt;a class="link" href="https://www.wch-ic.com/downloads/CH9121DS1_PDF.html" target="_blank" rel="noopener"
>https://www.wch-ic.com/downloads/CH9121DS1_PDF.html&lt;/a>&lt;/p>
&lt;p>今回はキャチロボ用にFeetechのシリアルサーボをイーサネット経由で動かそうとしていたが，Feetechのボーレートは以下から選択するしかないようになっている．&lt;/p>
&lt;p>&lt;img src="http://blog.hirobon1690.com/post/best-buy-2025/image-1.png"
width="388"
height="480"
srcset="http://blog.hirobon1690.com/post/best-buy-2025/image-1_huff695a9abf299498571823242c4ec393_89117_480x0_resize_box_3.png 480w, http://blog.hirobon1690.com/post/best-buy-2025/image-1_huff695a9abf299498571823242c4ec393_89117_1024x0_resize_box_3.png 1024w"
loading="lazy"
alt="Feetechのボーレート選択肢"
class="gallery-image"
data-flex-grow="80"
data-flex-basis="194px"
>&lt;/p>
&lt;p>引用：&lt;a class="link" href="https://www.feetechrc.com/Data/feetechrc/upload/file/20201127/start%20%20tutorial201015.pdf" target="_blank" rel="noopener"
>https://www.feetechrc.com/Data/feetechrc/upload/file/20201127/start%20%20tutorial201015.pdf&lt;/a>&lt;/p>
&lt;p>これは&lt;strong>115200以上のボーレートが9600の倍数になっていないFeetechさんサイドの仕様が意味不明&lt;/strong>なのだが，これだと115200で動かすしかなく，応答性に遅延を感じるレベルだったのであえなく採用を諦めた．&lt;/p>
&lt;h2 id="買わなくてよかったもの">買わなくてよかったもの&lt;/h2>
&lt;h3 id="ankerのmagsafe充電器とダイソーのmagsafeリング">AnkerのMagSafe充電器とダイソーのMagSafeリング&lt;/h3>
&lt;p>&lt;img src="http://blog.hirobon1690.com/post/best-buy-2025/image-3.png"
width="1347"
height="1500"
srcset="http://blog.hirobon1690.com/post/best-buy-2025/image-3_huc2c0eba85a34ae812ef3f69bcb495277_377787_480x0_resize_box_3.png 480w, http://blog.hirobon1690.com/post/best-buy-2025/image-3_huc2c0eba85a34ae812ef3f69bcb495277_377787_1024x0_resize_box_3.png 1024w"
loading="lazy"
alt="MagSafe充電器"
class="gallery-image"
data-flex-grow="89"
data-flex-basis="215px"
>&lt;br>
&lt;style>
@media (prefers-color-scheme: dark) {
.box{
background-color: #5b5b5b;
}
}
.box{
width: 100%;
max-width: 500px;
height: 100px;
background-color: var(--link-card-background) !important;
color: var(--accent-color);
border-radius: 10px;
overflow: hidden;
display: flex!important;
vertical-align: top!important;
box-shadow: 0 0 5px 1px rgba(0, 0, 0, .2);
}
.box:hover{
opacity: 0.8;
}
.text{
margin: 5px 0 0 10px;
}
.img-class {
width: 100px;
height: 100px!important;
object-fit: cover;
}
.url{
font-size: smaller;
color: lightgray;
margin: 0 0 0 10px;
color: var(--accent-color-darker);
}
.flex{
display: flex;
}
&lt;/style>
&lt;a class='flex' href="https://www.amazon.co.jp/dp/B0DW2SYD5H" target="_blank" rel="noopener noreferrer">
&lt;div class='box'>
&lt;img src="http://blog.hirobon1690.com/img/default_huf044c2fbafe082fc6235c0e83e8785d7_957_200x200_fill_q100_h2_box_center_3.webp" class='img-class'>
&lt;div>
&lt;p class='text'>Anker Zolo Wireless Charger&lt;/p>
&lt;p class='url'>https://www.amazon.co.jp/dp/B0DW2SYD5H&lt;/p>
&lt;/div>
&lt;/div>
&lt;/a>&lt;/p>
&lt;p>当初はiPhoneのStandby Mode的な運用を目論んで購入したが，&lt;strong>わざわざ爆熱になって，それでいて遅い充電などなんの需要もない&lt;/strong>ことにやってみて気がついた．ほんとに使ってないのでメルカリに放出しようかな．&lt;/p>
&lt;h2 id="以上">以上！&lt;/h2>
&lt;p>いまは60%キーボードを血眼になって探しています．みなさんよいお年を～&lt;/p></description></item><item><title>2024 今年買ってよかったもの &amp; 買わなくてもよかったもの</title><link>http://blog.hirobon1690.com/post/best-buy-2024/</link><pubDate>Fri, 27 Dec 2024 01:34:00 +0900</pubDate><guid>http://blog.hirobon1690.com/post/best-buy-2024/</guid><description>&lt;img src="http://blog.hirobon1690.com/post/best-buy-2024/5.jpg" alt="Featured image of post 2024 今年買ってよかったもの &amp; 買わなくてもよかったもの" />&lt;p>1回書いてみたかった&lt;br>
順不同です&lt;/p>
&lt;h2 id="今年買ってよかったもの">今年買ってよかったもの&lt;/h2>
&lt;h3 id="amazonベーシック-デュアルモニターアーム-最大32インチ">Amazonベーシック デュアルモニターアーム (最大32インチ)&lt;/h3>
&lt;p>&lt;a class="link" href="https://www.amazon.co.jp/dp/B0CQTPZNV8" target="_blank" rel="noopener"
>https://www.amazon.co.jp/dp/B0CQTPZNV8&lt;/a>&lt;/p>
&lt;p>購入時価格 ¥2,973&lt;/p>
&lt;p>&lt;img src="http://blog.hirobon1690.com/post/best-buy-2024/1.jpg"
width="1355"
height="1323"
srcset="http://blog.hirobon1690.com/post/best-buy-2024/1_hu0c7bc2bfcdc45ff19e5f72459c96d0f6_41575_480x0_resize_q75_box.jpg 480w, http://blog.hirobon1690.com/post/best-buy-2024/1_hu0c7bc2bfcdc45ff19e5f72459c96d0f6_41575_1024x0_resize_q75_box.jpg 1024w"
loading="lazy"
alt="Amazonベーシック デュアルモニターアーム"
class="gallery-image"
data-flex-grow="102"
data-flex-basis="245px"
>&lt;/p>
&lt;p>研究室用に買いました．特にぐらつくことなく最高．3000円未満で名の知れているメーカー（中身は中華OEMだろうけど）が買えるのはデカい．&lt;br>
モニターアームは正義なので全員買いましょう．&lt;/p>
&lt;h3 id="quntis-デスクライト-usbライト-モニターライト-52cm-バーライト">Quntis デスクライト USBライト モニターライト 52cm バーライト&lt;/h3>
&lt;p>&lt;a class="link" href="https://www.amazon.co.jp/dp/B08T6H2W93" target="_blank" rel="noopener"
>https://www.amazon.co.jp/dp/B08T6H2W93&lt;/a>&lt;/p>
&lt;p>購入時価格 ¥4,457&lt;/p>
&lt;p>&lt;img src="http://blog.hirobon1690.com/post/best-buy-2024/2.jpg"
width="1462"
height="1225"
srcset="http://blog.hirobon1690.com/post/best-buy-2024/2_hu6f7f8185df6f817c190245b20159adcd_40675_480x0_resize_q75_box.jpg 480w, http://blog.hirobon1690.com/post/best-buy-2024/2_hu6f7f8185df6f817c190245b20159adcd_40675_1024x0_resize_q75_box.jpg 1024w"
loading="lazy"
alt="Quntis デスクライト USBライト モニターライト 52cm バーライト"
class="gallery-image"
data-flex-grow="119"
data-flex-basis="286px"
>&lt;/p>
&lt;p>同じく研究室用．蛍光灯のスタンドに慣れていると少し暗いかな．まぁ必要十分です．値段もBenQとかに比べたら安いし．でも自宅で使おうとは思わないかも．&lt;/p>
&lt;h3 id="パーツキャビネット-樹脂製-引出小60個タイプ">パーツキャビネット 樹脂製 引出小×60個タイプ&lt;/h3>
&lt;p>&lt;a class="link" href="https://www.monotaro.com/p/1878/4545/" target="_blank" rel="noopener"
>https://www.monotaro.com/p/1878/4545/&lt;/a>&lt;/p>
&lt;p>購入時価格 ¥3,051&lt;/p>
&lt;p>&lt;img src="http://blog.hirobon1690.com/post/best-buy-2024/4.png"
width="621"
height="636"
srcset="http://blog.hirobon1690.com/post/best-buy-2024/4_hu677fd262f68569ec5c4fcbedb8605610_488788_480x0_resize_box_3.png 480w, http://blog.hirobon1690.com/post/best-buy-2024/4_hu677fd262f68569ec5c4fcbedb8605610_488788_1024x0_resize_box_3.png 1024w"
loading="lazy"
alt="パーツキャビネット 樹脂製 引出小×60個タイプ"
class="gallery-image"
data-flex-grow="97"
data-flex-basis="234px"
>&lt;/p>
&lt;p>電子工作系の部品は全てSeriaのShikiriケースに入れていたのですが，数が多くなりすぎたのとShikiriケースの耐久性が低いことがわかったので導入．ラベルを付けて管理しており，部品を取り出すときのストレスが圧倒的に減った．&lt;/p>
&lt;p>&lt;img src="http://blog.hirobon1690.com/post/best-buy-2024/5.jpg"
width="2997"
height="2422"
srcset="http://blog.hirobon1690.com/post/best-buy-2024/5_hucf5f95bfbaa00228b89ed90518ccd60a_1425728_480x0_resize_q75_box.jpg 480w, http://blog.hirobon1690.com/post/best-buy-2024/5_hucf5f95bfbaa00228b89ed90518ccd60a_1425728_1024x0_resize_q75_box.jpg 1024w"
loading="lazy"
alt="my部品棚"
class="gallery-image"
data-flex-grow="123"
data-flex-basis="296px"
>&lt;/p>
&lt;p>モノタロウオレンジは気に食わないので，適当なラッカースプレーで黒にしました．もう1個増やすか検討中．&lt;/p>
&lt;h3 id="youtube-premium">YouTube Premium&lt;/h3>
&lt;p>&lt;a class="link" href="https://www.youtube.com/premium" target="_blank" rel="noopener"
>https://www.youtube.com/premium&lt;/a>&lt;/p>
&lt;p>月額 ¥780（学割）&lt;/p>
&lt;p>&lt;img src="http://blog.hirobon1690.com/post/best-buy-2024/3.png"
width="1066"
height="595"
srcset="http://blog.hirobon1690.com/post/best-buy-2024/3_hua88b9a23f0f242285c3020f8c4192ca4_99222_480x0_resize_box_3.png 480w, http://blog.hirobon1690.com/post/best-buy-2024/3_hua88b9a23f0f242285c3020f8c4192ca4_99222_1024x0_resize_box_3.png 1024w"
loading="lazy"
alt="YouTube Premium"
class="gallery-image"
data-flex-grow="179"
data-flex-basis="429px"
>&lt;/p>
&lt;p>今年ようやく入りました．主には飛ばせない広告が増えてきたことと，&lt;a class="link" href="https://support.google.com/youtube/thread/297889220/" target="_blank" rel="noopener"
>あまりにも下品な広告&lt;/a>にうんざりしたため．あと&lt;a class="link" href="https://japan.cnet.com/article/35217861/" target="_blank" rel="noopener"
>こんな話&lt;/a>もあったので．思う壺のような気もするが．私は作業時にiPadで動画を流しておくことが多いのだが，その場合ブラウザより公式クライアントのほうが圧倒的にストレスフリーで操作できる．課金することでPicture in Pictureも使えるし，YouTube Musicもおまけでついてくるしこの値段ならかなりよき．&lt;/p>
&lt;h2 id="買わなくてよかったもの">買わなくてよかったもの&lt;/h2>
&lt;h3 id="inateck-キーボードケース-ipad-air-11インチ-2024第5世代第4世代-109インチ20222020">Inateck キーボードケース iPad Air 11インチ 2024/第5世代/第4世代 10.9インチ（2022/2020）&lt;/h3>
&lt;p>&lt;a class="link" href="https://www.amazon.co.jp/dp/B0C65MB4M9" target="_blank" rel="noopener"
>https://www.amazon.co.jp/dp/B0C65MB4M9&lt;/a>&lt;/p>
&lt;p>購入時価格 ¥4,983&lt;/p>
&lt;p>&lt;img src="http://blog.hirobon1690.com/post/best-buy-2024/6.jpg"
width="1500"
height="1236"
srcset="http://blog.hirobon1690.com/post/best-buy-2024/6_hu3cfd4906c4b77503e7277c2162169173_143850_480x0_resize_q75_box.jpg 480w, http://blog.hirobon1690.com/post/best-buy-2024/6_hu3cfd4906c4b77503e7277c2162169173_143850_1024x0_resize_q75_box.jpg 1024w"
loading="lazy"
alt="Inateck キーボードケース"
class="gallery-image"
data-flex-grow="121"
data-flex-basis="291px"
>&lt;/p>
&lt;p>&lt;span style="font-size: 300%; font-weight:bold">結局iPadにキーボードなんて要らないんですよ！！！！！！！！！！！&lt;/span>&lt;br>
iPadのキーボードを買って「要らねえなぁ」ってなるのは2回目．学べ．&lt;/p>
&lt;h3 id="ソリッドステートリレーssrキット-25a20aタイプ">ソリッド・ステート・リレー(SSR)キット 25A(20A)タイプ&lt;/h3>
&lt;p>&lt;a class="link" href="https://akizukidenshi.com/catalog/g/g100203/" target="_blank" rel="noopener"
>https://akizukidenshi.com/catalog/g/g100203/&lt;/a>&lt;/p>
&lt;p>購入時価格 忘れた&lt;/p>
&lt;p>&lt;img src="http://blog.hirobon1690.com/post/best-buy-2024/7.jpg"
width="320"
height="240"
srcset="http://blog.hirobon1690.com/post/best-buy-2024/7_hu73fd1100dabb1a5ce53bf018b318ae1b_13105_480x0_resize_q75_box.jpg 480w, http://blog.hirobon1690.com/post/best-buy-2024/7_hu73fd1100dabb1a5ce53bf018b318ae1b_13105_1024x0_resize_q75_box.jpg 1024w"
loading="lazy"
alt="ソリッド・ステート・リレー(SSR)キット 25A(20A)タイプ"
class="gallery-image"
data-flex-grow="133"
data-flex-basis="320px"
>&lt;/p>
&lt;p>3Dプリンタをオンオフするスイッチを自作しようとしていたが，AC100をいじるのはやっぱり怖いので結局&lt;a class="link" href="https://hirobon1690.github.io/post/mainsail-tplink/" target="_blank" rel="noopener"
>既製品を使っている&lt;/a>．&lt;/p>
&lt;h2 id="以上">以上！&lt;/h2>
&lt;p>思い出したら追記するかもしれません&lt;br>
皆さまよいお年を～～～&lt;/p></description></item><item><title>見せてもらおうか，M4チップの実力とやらを</title><link>http://blog.hirobon1690.com/post/mac-mini/</link><pubDate>Sat, 16 Nov 2024 00:00:00 +0900</pubDate><guid>http://blog.hirobon1690.com/post/mac-mini/</guid><description>&lt;img src="http://blog.hirobon1690.com/post/mac-mini/thumb.jpeg" alt="Featured image of post 見せてもらおうか，M4チップの実力とやらを" />&lt;h2 id="mac-miniを買った">Mac miniを買った&lt;/h2>
&lt;p>M4 Mac miniが満を持して登場したので購入した．&lt;/p>
&lt;blockquote class="twitter-tweet">&lt;p lang="ja" dir="ltr">すいません、思いついちゃったので… &lt;a href="https://t.co/K8cqqGKYz7">pic.twitter.com/K8cqqGKYz7&lt;/a>&lt;/p>&amp;mdash; Hirobon (@hirobon1690) &lt;a href="https://twitter.com/hirobon1690/status/1856332288231125441?ref_src=twsrc%5Etfw">November 12, 2024&lt;/a>&lt;/blockquote> &lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8">&lt;/script>
&lt;p>電源内蔵で12 cm四方，それでいてパフォーマンスがそのへんのx86より良い．最低スペックでもメモリ16GBで，学割 &lt;strong>$ 499&lt;/strong>！&lt;sup id="fnref:1">&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref">1&lt;/a>&lt;/sup> SSDは256GBしかないが，デスクトップである以上いくらでも外付けできるので一切問題にはならない．これは買うしかない．&lt;br>
今まで自宅でVPNサーバ・NASとして活躍していた&lt;a class="link" href="https://x.com/hirobon1690/status/1747219951738626210" target="_blank" rel="noopener"
>2014のMac mini&lt;/a>を1年足らずで売り飛ばして導入することとなった．&lt;/p>
&lt;h2 id="cpu性能">CPU性能&lt;/h2>
&lt;h3 id="aarch64">AArch64&lt;/h3>
&lt;p>性能評価には&lt;a class="link" href="https://www.geekbench.com/" target="_blank" rel="noopener"
>Geekbench 6&lt;/a>を用いた．&lt;/p>
&lt;p>AArch64でのパフォーマンス，特にシングルコア性能は流石の一言である．マルチコア性能を同ランクのCPUと比較すると12〜13世代のデスクトップ用i7くらいか．&lt;/p>
&lt;p>&lt;img src="http://blog.hirobon1690.com/post/mac-mini/001.png"
width="1716"
height="2362"
srcset="http://blog.hirobon1690.com/post/mac-mini/001_huf5f6ae001941a63824aafe8810deb8bd_307393_480x0_resize_box_3.png 480w, http://blog.hirobon1690.com/post/mac-mini/001_huf5f6ae001941a63824aafe8810deb8bd_307393_1024x0_resize_box_3.png 1024w"
loading="lazy"
alt="Native × AArch64"
class="gallery-image"
data-flex-grow="72"
data-flex-basis="174px"
>&lt;/p>
&lt;p>&lt;a class="link" href="https://browser.geekbench.com/v6/cpu/8801610" target="_blank" rel="noopener"
>https://browser.geekbench.com/v6/cpu/8801610&lt;/a>&lt;/p>
&lt;p>VMWareでWindowsの仮想環境を構築して回した場合もこのとおり．同世代のi7→i5にランクダウンするイメージ．&lt;/p>
&lt;p>&lt;img src="http://blog.hirobon1690.com/post/mac-mini/002.png"
width="1734"
height="2122"
srcset="http://blog.hirobon1690.com/post/mac-mini/002_hud7b2631e2f8e59261070c0b7242d88f5_297133_480x0_resize_box_3.png 480w, http://blog.hirobon1690.com/post/mac-mini/002_hud7b2631e2f8e59261070c0b7242d88f5_297133_1024x0_resize_box_3.png 1024w"
loading="lazy"
alt="VMWare × AArch64"
class="gallery-image"
data-flex-grow="81"
data-flex-basis="196px"
>&lt;/p>
&lt;h3 id="x86エミュレーション">x86エミュレーション&lt;/h3>
&lt;p>ARMでのパフォーマンスに比較して，Rosetta 2を使ったx86エミュレーションの結果は少し期待外れなものであった．スコア基準だから一概には言えないが，性能は半分またはそれ未満まで落ちる．事前情報では8割のスペック！とか聞いていたのだが，流石に夢を見すぎか．&lt;/p>
&lt;p>&lt;img src="http://blog.hirobon1690.com/post/mac-mini/003.png"
width="1742"
height="2172"
srcset="http://blog.hirobon1690.com/post/mac-mini/003_hu6dec0645ac070a842a0fdc5675c0bd6a_312197_480x0_resize_box_3.png 480w, http://blog.hirobon1690.com/post/mac-mini/003_hu6dec0645ac070a842a0fdc5675c0bd6a_312197_1024x0_resize_box_3.png 1024w"
loading="lazy"
alt="Rosetta 2"
class="gallery-image"
data-flex-grow="80"
data-flex-basis="192px"
>&lt;/p>
&lt;p>ちなみにWindowsでのエミュレーションでも同様程度の下がり方をする．&lt;/p>
&lt;p>&lt;img src="http://blog.hirobon1690.com/post/mac-mini/004.png"
width="1744"
height="2046"
srcset="http://blog.hirobon1690.com/post/mac-mini/004_hu73cab58be9cb80e14237c1ee56ade3a5_300228_480x0_resize_box_3.png 480w, http://blog.hirobon1690.com/post/mac-mini/004_hu73cab58be9cb80e14237c1ee56ade3a5_300228_1024x0_resize_box_3.png 1024w"
loading="lazy"
alt="Prism"
class="gallery-image"
data-flex-grow="85"
data-flex-basis="204px"
>&lt;/p>
&lt;p>グラフにするとこんな感じ．&lt;/p>
&lt;p>&lt;img src="http://blog.hirobon1690.com/post/mac-mini/005.png"
width="1582"
height="614"
srcset="http://blog.hirobon1690.com/post/mac-mini/005_hu13aedac659cc01159430dc30e2db4a7d_125683_480x0_resize_box_3.png 480w, http://blog.hirobon1690.com/post/mac-mini/005_hu13aedac659cc01159430dc30e2db4a7d_125683_1024x0_resize_box_3.png 1024w"
loading="lazy"
alt="graph"
class="gallery-image"
data-flex-grow="257"
data-flex-basis="618px"
>&lt;/p>
&lt;h2 id="グラフィック性能">グラフィック性能&lt;/h2>
&lt;p>ここはそんなに期待していなかったので省略．グラフィックが必要なら大人しくグラボを積むしかない．&lt;/p>
&lt;h2 id="まとめ">まとめ&lt;/h2>
&lt;p>ぶっちゃけ趣味開発ならARMで事足りるため，充分すぎる環境が手に入ったといえる．裏でファイルサーバを回していても余裕がある．x86に依存する作業とPCゲームに関しては引き続き愛機Zephyrusくんに頑張ってもらうことにする．&lt;/p>
&lt;h2 id="ちなみに">ちなみに&lt;/h2>
&lt;p>Geekbenchをx86エミュレーションで回すのに手こずったのでメモ．&lt;/p>
&lt;h3 id="mac">Mac&lt;/h3>
&lt;p>GeekbenchをRosettaで開く設定にしても，パフォーマンスの計測自体はARMで行われてしまう．&lt;br>
FinderのアプリケーションフォルダでGeekbenchを副ボタンでクリックし，パッケージの内容を表示をクリックする．&lt;/p>
&lt;p>&lt;img src="http://blog.hirobon1690.com/post/mac-mini/010.png"
width="686"
height="388"
srcset="http://blog.hirobon1690.com/post/mac-mini/010_huc23ba0930789970c1f64e20e4afbb1fb_134844_480x0_resize_box_3.png 480w, http://blog.hirobon1690.com/post/mac-mini/010_huc23ba0930789970c1f64e20e4afbb1fb_134844_1024x0_resize_box_3.png 1024w"
loading="lazy"
alt="パッケージの内容を表示"
class="gallery-image"
data-flex-grow="176"
data-flex-basis="424px"
>&lt;/p>
&lt;p>&lt;code>Contents/Resources/&lt;/code>と辿るとx86用の実行ファイル&lt;code>geekbench_x86_64&lt;/code>が現れるので，ダブルクリックして直接実行する．&lt;/p>
&lt;p>&lt;img src="http://blog.hirobon1690.com/post/mac-mini/011.png"
width="1378"
height="834"
srcset="http://blog.hirobon1690.com/post/mac-mini/011_hu774e7a60eb3b800c837fc40e4c49df93_252550_480x0_resize_box_3.png 480w, http://blog.hirobon1690.com/post/mac-mini/011_hu774e7a60eb3b800c837fc40e4c49df93_252550_1024x0_resize_box_3.png 1024w"
loading="lazy"
alt="geekbench_x86_64"
class="gallery-image"
data-flex-grow="165"
data-flex-basis="396px"
>&lt;/p>
&lt;p>アクティビティモニタを見ると種類: Intelで実行されていることが確認できる．&lt;/p>
&lt;p>&lt;img src="http://blog.hirobon1690.com/post/mac-mini/012.png"
width="3712"
height="1630"
srcset="http://blog.hirobon1690.com/post/mac-mini/012_hu21358a0345d9b5be7861f743e9200da6_3028913_480x0_resize_box_3.png 480w, http://blog.hirobon1690.com/post/mac-mini/012_hu21358a0345d9b5be7861f743e9200da6_3028913_1024x0_resize_box_3.png 1024w"
loading="lazy"
alt="アクティビティモニタ"
class="gallery-image"
data-flex-grow="227"
data-flex-basis="546px"
>&lt;/p>
&lt;h3 id="windows">Windows&lt;/h3>
&lt;p>ARM環境で普通にインストールするとAArch64のバイナリしか展開されない．&lt;/p>
&lt;p>&lt;img src="http://blog.hirobon1690.com/post/mac-mini/006.png"
width="554"
height="332"
srcset="http://blog.hirobon1690.com/post/mac-mini/006_hucb14b09edc1c9902eb1babe2ff321623_25953_480x0_resize_box_3.png 480w, http://blog.hirobon1690.com/post/mac-mini/006_hucb14b09edc1c9902eb1babe2ff321623_25953_1024x0_resize_box_3.png 1024w"
loading="lazy"
alt="ARMしかないスクショ"
class="gallery-image"
data-flex-grow="166"
data-flex-basis="400px"
>&lt;/p>
&lt;p>インストーラのexeファイルを&lt;a class="link" href="https://7-zip.opensource.jp/" target="_blank" rel="noopener"
>7-Zip&lt;/a>で展開する．&lt;/p>
&lt;p>&lt;img src="http://blog.hirobon1690.com/post/mac-mini/007.png"
width="1418"
height="696"
srcset="http://blog.hirobon1690.com/post/mac-mini/007_hu1d553cb531b4941270eaf9a969ab4595_112514_480x0_resize_box_3.png 480w, http://blog.hirobon1690.com/post/mac-mini/007_hu1d553cb531b4941270eaf9a969ab4595_112514_1024x0_resize_box_3.png 1024w"
loading="lazy"
alt="7-Zipで展開"
class="gallery-image"
data-flex-grow="203"
data-flex-basis="488px"
>&lt;/p>
&lt;p>展開フォルダを開くとx86用の実行ファイル&lt;code>geekbench_x86_64.exe&lt;/code>が現れるので，ダブルクリックして直接実行する．&lt;/p>
&lt;p>&lt;img src="http://blog.hirobon1690.com/post/mac-mini/008.png"
width="534"
height="502"
srcset="http://blog.hirobon1690.com/post/mac-mini/008_hucbb25d5ee36c19f5cd2b87c4a1f91606_39567_480x0_resize_box_3.png 480w, http://blog.hirobon1690.com/post/mac-mini/008_hucbb25d5ee36c19f5cd2b87c4a1f91606_39567_1024x0_resize_box_3.png 1024w"
loading="lazy"
alt="geekbench_x86_64.exe"
class="gallery-image"
data-flex-grow="106"
data-flex-basis="255px"
>&lt;/p>
&lt;p>タスクマネージャを見るとx64モードで実行されていることが確認できる．&lt;/p>
&lt;p>&lt;img src="http://blog.hirobon1690.com/post/mac-mini/009.png"
width="3142"
height="1738"
srcset="http://blog.hirobon1690.com/post/mac-mini/009_huc720e922f6b442a48fe4b0481ef28374_2384442_480x0_resize_box_3.png 480w, http://blog.hirobon1690.com/post/mac-mini/009_huc720e922f6b442a48fe4b0481ef28374_2384442_1024x0_resize_box_3.png 1024w"
loading="lazy"
alt="タスクマネージャ"
class="gallery-image"
data-flex-grow="180"
data-flex-basis="433px"
>&lt;/p>
&lt;div class="footnotes" role="doc-endnotes">
&lt;hr>
&lt;ol>
&lt;li id="fn:1">
&lt;p>日本円では¥79,800. 円安…&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;/ol>
&lt;/div></description></item><item><title>WindowsからYu Gothic UIを駆逐する</title><link>http://blog.hirobon1690.com/post/windows-system-font/</link><pubDate>Tue, 19 Mar 2024 00:00:00 +0900</pubDate><guid>http://blog.hirobon1690.com/post/windows-system-font/</guid><description>&lt;img src="http://blog.hirobon1690.com/post/windows-system-font/001.png" alt="Featured image of post WindowsからYu Gothic UIを駆逐する" />&lt;h2 id="ツールをつくった">ツールをつくった&lt;/h2>
&lt;p>Windows 10の時代からシステムフォントのYu Gothic UIが嫌いすぎて，既存フォントのプロパティを編集してYu Gothic UIという名前の偽装フォントをインストールして置き換えたり，レジストリをいじり倒すなどしてフォント変更を行っていた．&lt;br>
しかし，これらの手順はあまりにも煩雑であるほか，以前更新していたブログの該当記事に未だにコンスタントにアクセスがあることから需要があるものと判断し，ツールをつくることにした．&lt;/p>
&lt;p>以下が作成したツールである．&lt;br>
&lt;style>
@media (prefers-color-scheme: dark) {
.box{
background-color: #5b5b5b;
}
}
.box{
width: 100%;
max-width: 500px;
height: 100px;
background-color: var(--link-card-background) !important;
color: var(--accent-color);
border-radius: 10px;
overflow: hidden;
display: flex!important;
vertical-align: top!important;
box-shadow: 0 0 5px 1px rgba(0, 0, 0, .2);
}
.box:hover{
opacity: 0.8;
}
.text{
margin: 5px 0 0 10px;
}
.img-class {
width: 100px;
height: 100px!important;
object-fit: cover;
}
.url{
font-size: smaller;
color: lightgray;
margin: 0 0 0 10px;
color: var(--accent-color-darker);
}
.flex{
display: flex;
}
&lt;/style>
&lt;a class='flex' href="https://github.com/hirobon1690/System-Font-Changer-for-Windows10-11" target="_blank" rel="noopener noreferrer">
&lt;div class='box'>
&lt;img src="http://blog.hirobon1690.com/System-Font-Changer-for-Windows10-11_14191865158856205357_hu8d620f7b93b493164a17186d65b2da6d_0_200x200_fill_q100_h2_box_center_3.webp" class='img-class'>
&lt;div>
&lt;p class='text'>System Font Changer for Windows 10/11&lt;/p>
&lt;p class='url'>https://github.com/hirobon1690/System-Font-Changer-for-Windows10-11&lt;/p>
&lt;/div>
&lt;/div>
&lt;/a>&lt;/p>
&lt;p>&lt;img src="http://blog.hirobon1690.com/post/windows-system-font/001.png"
width="1933"
height="1417"
srcset="http://blog.hirobon1690.com/post/windows-system-font/001_hu4bb8be5375b0a3366a95dbf17419a615_319485_480x0_resize_box_3.png 480w, http://blog.hirobon1690.com/post/windows-system-font/001_hu4bb8be5375b0a3366a95dbf17419a615_319485_1024x0_resize_box_3.png 1024w"
loading="lazy"
alt="フォントを変更した例"
class="gallery-image"
data-flex-grow="136"
data-flex-basis="327px"
>&lt;/p>
&lt;h2 id="使い方の動画">使い方の動画&lt;/h2>
&lt;p>作成中&lt;/p>
&lt;h2 id="技術話">技術話&lt;/h2>
&lt;ul>
&lt;li>
&lt;p>&lt;a class="link" href="https://fontforge.org/en-US/" target="_blank" rel="noopener"
>FontForge&lt;/a>の&lt;a class="link" href="https://fontforge.org/docs/scripting/python.html" target="_blank" rel="noopener"
>Python API&lt;/a>を大いに活用している．Windowsはフォント名とPostscript名が同じフォントを同一とみなす仕様があるようで，これを利用している．&lt;/p>
&lt;/li>
&lt;li>
&lt;p>本来システムフォントは削除できないのだが，以下の記事にあるようにフォントの所有権を変更することによって実現している．&lt;br>
failed to fetch remote resource: Forbidden
&lt;style>
@media (prefers-color-scheme: dark) {
.box{
background-color: #5b5b5b;
}
}
.box{
width: 100%;
max-width: 500px;
height: 100px;
background-color: var(--link-card-background) !important;
color: var(--accent-color);
border-radius: 10px;
overflow: hidden;
display: flex!important;
vertical-align: top!important;
box-shadow: 0 0 5px 1px rgba(0, 0, 0, .2);
}
.box:hover{
opacity: 0.8;
}
.text{
margin: 5px 0 0 10px;
}
.img-class {
width: 100px;
height: 100px!important;
object-fit: cover;
}
.url{
font-size: smaller;
color: lightgray;
margin: 0 0 0 10px;
color: var(--accent-color-darker);
}
.flex{
display: flex;
}
&lt;/style>
&lt;a class='flex' href="https://qiita.com/ikikuchi/items/7a941ac45b6e97a14058" target="_blank" rel="noopener noreferrer">
&lt;div class='box'>
&lt;img src="" class='img-class'>
&lt;div>
&lt;p class='text'>【Windows10】システムフォント（游ゴシック）を別フォントに変更する&lt;/p>
&lt;p class='url'>https://qiita.com/ikikuchi/items/7a941ac45b6e97a14058&lt;/p>
&lt;/div>
&lt;/div>
&lt;/a>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>既存ツールとして&lt;a class="link" href="https://www.wintools.info/index.php/advanced-system-font-changer" target="_blank" rel="noopener"
>Advanced System Font Changer&lt;/a>や&lt;a class="link" href="https://www.tatsu-syo.info/MySoft/WinCust/index.html" target="_blank" rel="noopener"
>Meiryo UIも大っきらい!!&lt;/a>などが挙げられるが，これらのツールはレジストリ変更のみで反映される部分のみのフォントを変更している（ものと私は認識している）．私のツールはシステムフォントそのものを置き換えるため， &lt;strong>ほぼすべての範囲にフォントが反映される点に優位性がある&lt;/strong>．しかしながら，これにはリスクも伴い，既存ツールと比較し表示上の不具合やOSの不具合が発生する可能性が高い．また，元の状態に戻すのが煩雑である．&lt;/p>
&lt;/li>
&lt;/ul></description></item><item><title>Moonrakerの電源管理で任意のスマートプラグを使う(Tplink P105)</title><link>http://blog.hirobon1690.com/post/mainsail-tplink/</link><pubDate>Wed, 24 Jan 2024 00:00:00 +0900</pubDate><guid>http://blog.hirobon1690.com/post/mainsail-tplink/</guid><description>&lt;img src="http://blog.hirobon1690.com/post/mainsail-tplink/001.png" alt="Featured image of post Moonrakerの電源管理で任意のスマートプラグを使う(Tplink P105)" />&lt;h2 id="about">About&lt;/h2>
&lt;p>&lt;img src="http://blog.hirobon1690.com/post/mainsail-tplink/001.png"
width="910"
height="469"
srcset="http://blog.hirobon1690.com/post/mainsail-tplink/001_hu1b81ac19835b8092c106845ff271fc95_30863_480x0_resize_box_3.png 480w, http://blog.hirobon1690.com/post/mainsail-tplink/001_hu1b81ac19835b8092c106845ff271fc95_30863_1024x0_resize_box_3.png 1024w"
loading="lazy"
alt="Moonrakerの電源管理機能"
class="gallery-image"
data-flex-grow="194"
data-flex-basis="465px"
>&lt;/p>
&lt;p>KlipperのAPIであるMoonrakerには&lt;a class="link" href="https://moonraker.readthedocs.io/en/latest/configuration/#power" target="_blank" rel="noopener"
>電源管理機能&lt;/a>があるが，&lt;/p>
&lt;ul>
&lt;li>対応するスマートプラグの種類が少ない&lt;/li>
&lt;li>サーボなどでスイッチを動かそうとした場合，PWMを出力するオプションがない&lt;/li>
&lt;li>任意のGCodeを指定してgcode_shell_commandでシェルスクリプトを起動することができるが，これはプリンタ側のマイコンとの通信が確立している必要があるため &lt;strong>電源ON時に使うことができない&lt;/strong>&lt;/li>
&lt;/ul>
&lt;p>という欠点がある．自分は今までサーボで電源をON/OFFしており，その後TP-Link P105というスマートプラグに乗り換えたという経緯があり，今回はこれを解決した方法を説明する．&lt;/p>
&lt;blockquote class="twitter-tweet" data-media-max-width="560">&lt;p lang="ja" dir="ltr">3Dプリンタ用のスマートプラグ(物理)&lt;br>つくりました &lt;a href="https://t.co/n3RfNQwTx8">pic.twitter.com/n3RfNQwTx8&lt;/a>&lt;/p>&amp;mdash; Hirobon (@hirobon1690) &lt;a href="https://twitter.com/hirobon1690/status/1583855386175885312?ref_src=twsrc%5Etfw">October 22, 2022&lt;/a>&lt;/blockquote> &lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8">&lt;/script>
&lt;style>
@media (prefers-color-scheme: dark) {
.box{
background-color: #5b5b5b;
}
}
.box{
width: 100%;
max-width: 500px;
height: 100px;
background-color: var(--link-card-background) !important;
color: var(--accent-color);
border-radius: 10px;
overflow: hidden;
display: flex!important;
vertical-align: top!important;
box-shadow: 0 0 5px 1px rgba(0, 0, 0, .2);
}
.box:hover{
opacity: 0.8;
}
.text{
margin: 5px 0 0 10px;
}
.img-class {
width: 100px;
height: 100px!important;
object-fit: cover;
}
.url{
font-size: smaller;
color: lightgray;
margin: 0 0 0 10px;
color: var(--accent-color-darker);
}
.flex{
display: flex;
}
&lt;/style>
&lt;a class='flex' href="https://www.amazon.co.jp/dp/B08G1G1DVT" target="_blank" rel="noopener noreferrer">
&lt;div class='box'>
&lt;img src="http://blog.hirobon1690.com/img/default_huf044c2fbafe082fc6235c0e83e8785d7_957_200x200_fill_q100_h2_box_center_3.webp" class='img-class'>
&lt;div>
&lt;p class='text'>TP-Link P105 - Amazon&lt;/p>
&lt;p class='url'>https://www.amazon.co.jp/dp/B08G1G1DVT&lt;/p>
&lt;/div>
&lt;/div>
&lt;/a>
&lt;h2 id="やりたいこと">やりたいこと&lt;/h2>
&lt;p>Moonrakerには電源管理でHTTPリクエストを飛ばす機能があり，Pythonでそれを受けるローカルサーバを立てることで任意の処理を実行可能にする．このやり方では別途Homebridgeのインスタンスを立てる必要などもないためシンプルかつ軽量に実装できる．&lt;/p>
&lt;p>&lt;img src="http://blog.hirobon1690.com/post/mainsail-tplink/002.png"
width="1098"
height="446"
srcset="http://blog.hirobon1690.com/post/mainsail-tplink/002_hu2b59b276a0ac496d8aac4b2a4a9a1650_71798_480x0_resize_box_3.png 480w, http://blog.hirobon1690.com/post/mainsail-tplink/002_hu2b59b276a0ac496d8aac4b2a4a9a1650_71798_1024x0_resize_box_3.png 1024w"
loading="lazy"
alt="イメージ図"
class="gallery-image"
data-flex-grow="246"
data-flex-basis="590px"
>&lt;/p>
&lt;p>ここではTPLink P105を例として説明するが，他の方法を取る場合でも流れは同じである（適宜コードを読み替えてほしい）&lt;/p>
&lt;p>※任意のと言ったがPython経由で操作できるスマートプラグである必要がある&lt;/p>
&lt;h3 id="pythonでサーバ部分を書く">Pythonでサーバ部分を書く&lt;/h3>
&lt;p>適当なディレクトリにpythonコードを作成する．&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">mkdir ~/src
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">cd&lt;/span> ~/src
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">touch power.py
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>内容を&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;span class="lnt">47
&lt;/span>&lt;span class="lnt">48
&lt;/span>&lt;span class="lnt">49
&lt;/span>&lt;span class="lnt">50
&lt;/span>&lt;span class="lnt">51
&lt;/span>&lt;span class="lnt">52
&lt;/span>&lt;span class="lnt">53
&lt;/span>&lt;span class="lnt">54
&lt;/span>&lt;span class="lnt">55
&lt;/span>&lt;span class="lnt">56
&lt;/span>&lt;span class="lnt">57
&lt;/span>&lt;span class="lnt">58
&lt;/span>&lt;span class="lnt">59
&lt;/span>&lt;span class="lnt">60
&lt;/span>&lt;span class="lnt">61
&lt;/span>&lt;span class="lnt">62
&lt;/span>&lt;span class="lnt">63
&lt;/span>&lt;span class="lnt">64
&lt;/span>&lt;span class="lnt">65
&lt;/span>&lt;span class="lnt">66
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">http.server&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">BaseHTTPRequestHandler&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">HTTPServer&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">asyncio&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">os&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">tapo&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">ApiClient&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">IP&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;TapoのIP&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">USER&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;Tapoのユーザ名&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">PASS&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;Tapoのパスワード&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">Tapo&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="fm">__init__&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">ip_address&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">username&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">password&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">ip_address&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ip_address&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">username&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">username&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">password&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">password&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">async&lt;/span> &lt;span class="k">def&lt;/span> &lt;span class="nf">conncet&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">client&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ApiClient&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">username&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">password&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">device&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">await&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">client&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">p105&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">ip_address&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">async&lt;/span> &lt;span class="k">def&lt;/span> &lt;span class="nf">on&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">await&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">device&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">on&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">async&lt;/span> &lt;span class="k">def&lt;/span> &lt;span class="nf">off&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">await&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">device&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">off&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">async&lt;/span> &lt;span class="k">def&lt;/span> &lt;span class="nf">status&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">device_info&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">await&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">device&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get_device_info&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">device_info&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">to_dict&lt;/span>&lt;span class="p">()[&lt;/span>&lt;span class="s1">&amp;#39;device_on&amp;#39;&lt;/span>&lt;span class="p">]:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="s1">&amp;#39;on&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">else&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="s1">&amp;#39;off&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">tapo&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Tapo&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">IP&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">USER&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">PASS&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">SimpleHTTPRequestHandler&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">BaseHTTPRequestHandler&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">do_GET&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">send_response&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">200&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">send_header&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;Content-type&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;text/plain&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">end_headers&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">asyncio&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">run&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">tapo&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">conncet&lt;/span>&lt;span class="p">())&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">message&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 別のスマートプラグを使う場合やPWMを使う場合はここから下を適宜書き換える&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">path&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s1">&amp;#39;/on&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">asyncio&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">run&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">tapo&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">on&lt;/span>&lt;span class="p">())&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">message&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;on&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">elif&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">path&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s1">&amp;#39;/off&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">asyncio&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">run&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">tapo&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">off&lt;/span>&lt;span class="p">())&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">message&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;off&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">elif&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">path&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s1">&amp;#39;/status&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">message&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">asyncio&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">run&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">tapo&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">status&lt;/span>&lt;span class="p">())&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">wfile&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">write&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">message&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">encode&lt;/span>&lt;span class="p">())&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">run&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">server_class&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">HTTPServer&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">handler_class&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">SimpleHTTPRequestHandler&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">port&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">8000&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">server_address&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">port&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">httpd&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">server_class&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">server_address&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">handler_class&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;Server running on port &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">port&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">httpd&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">serve_forever&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">if&lt;/span> &lt;span class="vm">__name__&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s2">&amp;#34;__main__&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">run&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>依存関係（今回は&lt;a class="link" href="https://github.com/mihai-dinculescu/tapo" target="_blank" rel="noopener"
>このライブラリ&lt;/a>を使う）をインストールして&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">sudo pip install tapo
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>実行する&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">sudo cdmod +x ~/src/power.py
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo python ~/src/power.py
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>出力が&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">Server running on port &lt;span class="m">8000&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>となれば実行はできている．&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">sudo apt install curl
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">curl http://localhost:8000/on
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">curl http://localhost:8000/status
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">curl http://localhost:8000/off
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">curl http://localhost:8000/status
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>を1行ずつ実行し，うまく実行されればスクリプトの作成は成功である．&lt;/p>
&lt;h3 id="os起動時に自動実行されるようにする">OS起動時に自動実行されるようにする&lt;/h3>
&lt;h4 id="起動用シェルスクリプトの作成">起動用シェルスクリプトの作成&lt;/h4>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">touch ~/src/power.sh
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">nano ~/src/power.sh
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>内容を&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-sh" data-lang="sh">&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#!/usr/bin/env bash
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>python ~/src/power.py
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>として保存．&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">chmod +x ~/src/power.sh
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">~/src/power.sh
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>実行して起動するかを確認する．&lt;/p>
&lt;h4 id="serviceを作成">Serviceを作成&lt;/h4>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">sudo touch /etc/systemd/system/power/service
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo nano /etc/systemd/system/power/service
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>として内容を&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-service" data-lang="service">&lt;span class="line">&lt;span class="cl">&lt;span class="k">[Unit]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="na">Description&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">power&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">[Service]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="na">ExecStart&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">/home/[username]/src/power.sh&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">[Install]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="na">WantedBy&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">default.target&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>とする．usernameは各自の環境で置き換えてほ欲しい．&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">systemctl status power.service
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>として&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">○ manager.service - power
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> Loaded: loaded &lt;span class="o">(&lt;/span>/etc/systemd/system/power.service&lt;span class="p">;&lt;/span> disabled&lt;span class="p">;&lt;/span> vendor preset: enabled&lt;span class="o">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> Active: inactive &lt;span class="o">(&lt;/span>dead&lt;span class="o">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>となればよい．&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">sudo systemctl &lt;span class="nb">enable&lt;/span> power.service
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>として&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">sudo reboot
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>その後&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">systemctl status power.service
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>として&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">● power.service - power
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> Loaded: loaded &lt;span class="o">(&lt;/span>/etc/systemd/system/power.service&lt;span class="p">;&lt;/span> enabled&lt;span class="p">;&lt;/span> vendor preset: enabled&lt;span class="o">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> Active: active &lt;span class="o">(&lt;/span>running&lt;span class="o">)&lt;/span> since Wed 2024-01-24 09:19:02 UTC&lt;span class="p">;&lt;/span> 47s ago
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>といった出力が得られれば成功である．&lt;br>
ここで試しに&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">curl http://localhost:8000/on
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">curl http://localhost:8000/status
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">curl http://localhost:8000/off
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">curl http://localhost:8000/status
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>を実行して動作を確認する．&lt;/p>
&lt;h3 id="moonrakerの設定">Moonrakerの設定&lt;/h3>
&lt;p>ブラウザでMainsailの画面を開き，&lt;code>moonraker.conf&lt;/code>に以下の内容を追記する．&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">[power Plug]
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">type: http
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">on_url: http://localhost:8000/on
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">off_url: http://localhost:8000/off
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">status_url: http://localhost:8000/status
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">response_template: {http_request.last_response().text}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">bound_services: klipper
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">on_when_job_queued: True
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">[file_manager]
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">queue_gcode_uploads: True
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">[job_queue]
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">load_on_startup: True
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Save and Restartして，右上の電源ボタンから電源をオンオフできれば完了．&lt;/p>
&lt;p>&lt;img src="http://blog.hirobon1690.com/post/mainsail-tplink/003.png"
width="268"
height="447"
srcset="http://blog.hirobon1690.com/post/mainsail-tplink/003_hufbe2c68db040749646dd8991925a2fba_21106_480x0_resize_box_3.png 480w, http://blog.hirobon1690.com/post/mainsail-tplink/003_hufbe2c68db040749646dd8991925a2fba_21106_1024x0_resize_box_3.png 1024w"
loading="lazy"
alt="Mainsailの電源ボタン"
class="gallery-image"
data-flex-grow="59"
data-flex-basis="143px"
>&lt;/p>
&lt;p>スライサーからアップロードすると電源が自動的に入り印刷が開始されるようになる．&lt;/p>
&lt;h2 id="参考文献">参考文献&lt;/h2>
&lt;ul>
&lt;li>&lt;a class="link" href="https://zenn.dev/ochakumi/articles/5a8d1a3eeb890c" target="_blank" rel="noopener"
>Pythonのプログラムをマシンの起動時に毎回実行させる方法&lt;/a>&lt;/li>
&lt;li>&lt;a class="link" href="https://picalittle.tech/klipper-mainsail_tp-link_tapo_p105_install/" target="_blank" rel="noopener"
>Tp-Link [Tapo P105]をKlipper/Mainsailで制御し印刷完了時に電源を落とす方法&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>Expo×WSLでAndroidアプリをローカルビルドするのに手こずった記録</title><link>http://blog.hirobon1690.com/post/eas-wsl/</link><pubDate>Fri, 05 Jan 2024 00:00:00 +0900</pubDate><guid>http://blog.hirobon1690.com/post/eas-wsl/</guid><description>&lt;img src="http://blog.hirobon1690.com/post/eas-wsl/001.png" alt="Featured image of post Expo×WSLでAndroidアプリをローカルビルドするのに手こずった記録" />&lt;h2 id="about">About&lt;/h2>
&lt;style>
@media (prefers-color-scheme: dark) {
.box{
background-color: #5b5b5b;
}
}
.box{
width: 100%;
max-width: 500px;
height: 100px;
background-color: var(--link-card-background) !important;
color: var(--accent-color);
border-radius: 10px;
overflow: hidden;
display: flex!important;
vertical-align: top!important;
box-shadow: 0 0 5px 1px rgba(0, 0, 0, .2);
}
.box:hover{
opacity: 0.8;
}
.text{
margin: 5px 0 0 10px;
}
.img-class {
width: 100px;
height: 100px!important;
object-fit: cover;
}
.url{
font-size: smaller;
color: lightgray;
margin: 0 0 0 10px;
color: var(--accent-color-darker);
}
.flex{
display: flex;
}
&lt;/style>
&lt;a class='flex' href="https://reactnative.dev/" target="_blank" rel="noopener noreferrer">
&lt;div class='box'>
&lt;img src="http://blog.hirobon1690.com/img/default_huf044c2fbafe082fc6235c0e83e8785d7_957_200x200_fill_q100_h2_box_center_3.webp" class='img-class'>
&lt;div>
&lt;p class='text'>React Native&lt;/p>
&lt;p class='url'>https://reactnative.dev/&lt;/p>
&lt;/div>
&lt;/div>
&lt;/a>
&lt;p>&lt;a class="link" href="https://reactnative.dev/" target="_blank" rel="noopener"
>React Native&lt;/a>について調べていたら，&lt;a class="link" href="https://reactnative.dev/docs/environment-setup" target="_blank" rel="noopener"
>チュートリアル&lt;/a>で&lt;a class="link" href="https://expo.dev/" target="_blank" rel="noopener"
>Expo&lt;/a>というフレームワークを用いていた．これを使ってWindows&lt;sup id="fnref:1">&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref">1&lt;/a>&lt;/sup> (WSL)でAndroidのAPKをビルドしようとしたところ非常に手こずったのでメモしておく．&lt;/p>
&lt;h2 id="参考">参考&lt;/h2>
&lt;style>
@media (prefers-color-scheme: dark) {
.box{
background-color: #5b5b5b;
}
}
.box{
width: 100%;
max-width: 500px;
height: 100px;
background-color: var(--link-card-background) !important;
color: var(--accent-color);
border-radius: 10px;
overflow: hidden;
display: flex!important;
vertical-align: top!important;
box-shadow: 0 0 5px 1px rgba(0, 0, 0, .2);
}
.box:hover{
opacity: 0.8;
}
.text{
margin: 5px 0 0 10px;
}
.img-class {
width: 100px;
height: 100px!important;
object-fit: cover;
}
.url{
font-size: smaller;
color: lightgray;
margin: 0 0 0 10px;
color: var(--accent-color-darker);
}
.flex{
display: flex;
}
&lt;/style>
&lt;a class='flex' href="https://zenn.dev/tadaedo/scraps/6f989f2a104f76" target="_blank" rel="noopener noreferrer">
&lt;div class='box'>
&lt;img src="http://blog.hirobon1690.com/c3c550e35e_1776410988402077246_huafa99b97a5e11d7c1ed6ae9442255fe7_0_200x200_fill_q100_h2_box_center.webp" class='img-class'>
&lt;div>
&lt;p class='text'>eas build --local メモ - Zenn&lt;/p>
&lt;p class='url'>https://zenn.dev/tadaedo/scraps/6f989f2a104f76&lt;/p>
&lt;/div>
&lt;/div>
&lt;/a>
&lt;h2 id="前提">前提&lt;/h2>
&lt;p>以下がインストール済みとする:&lt;/p>
&lt;ul>
&lt;li>WSL (Ubuntu)&lt;/li>
&lt;li>nodejs, npmなど&lt;/li>
&lt;li>eas-cli&lt;/li>
&lt;/ul>
&lt;h2 id="手順">手順&lt;/h2>
&lt;h3 id="wsl特有のpathの無効化">WSL特有のPATHの無効化&lt;/h3>
&lt;p>WSLにはWindowsのPATHをUbuntu側にコピーする機能(!?)がデフォルトでオンになっている(!?)．混乱の元なのでこれを無効化する．&lt;br>
&lt;code>/etc/wsl.conf&lt;/code>に&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">[interop]
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">appendWindowsPath = false
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>を追記する．(ファイルが存在しない場合は作成する)&lt;/p>
&lt;h3 id="android-studioのインストール">Android Studioのインストール&lt;/h3>
&lt;style>
@media (prefers-color-scheme: dark) {
.box{
background-color: #5b5b5b;
}
}
.box{
width: 100%;
max-width: 500px;
height: 100px;
background-color: var(--link-card-background) !important;
color: var(--accent-color);
border-radius: 10px;
overflow: hidden;
display: flex!important;
vertical-align: top!important;
box-shadow: 0 0 5px 1px rgba(0, 0, 0, .2);
}
.box:hover{
opacity: 0.8;
}
.text{
margin: 5px 0 0 10px;
}
.img-class {
width: 100px;
height: 100px!important;
object-fit: cover;
}
.url{
font-size: smaller;
color: lightgray;
margin: 0 0 0 10px;
color: var(--accent-color-darker);
}
.flex{
display: flex;
}
&lt;/style>
&lt;a class='flex' href="https://developer.android.com/studio" target="_blank" rel="noopener noreferrer">
&lt;div class='box'>
&lt;img src="http://blog.hirobon1690.com/android-developers_10844255814550377746_hub249dac1c21106caa1d7a70b0b6b44bc_0_200x200_fill_q100_h2_box_center_3.webp" class='img-class'>
&lt;div>
&lt;p class='text'>Android Studio&lt;/p>
&lt;p class='url'>https://developer.android.com/studio&lt;/p>
&lt;/div>
&lt;/div>
&lt;/a>
&lt;p>&lt;a class="link" href="https://developer.android.com/studio" target="_blank" rel="noopener"
>公式サイト&lt;/a>からAndroid Studioをダウンロードし，&lt;code>.tar.gz&lt;/code>を展開．フォルダごと&lt;code>/opt/&lt;/code>に移動する．&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="nb">cd&lt;/span> ~/Downloads
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">tar -zxvf android-studio-2022.3.1.21-linux.tar.gz
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo mv android-studio /opt/
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>起動スクリプトを走らせる．&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">/opt/android-studio/bin/studio.sh
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>画面の指示に従って起動画面が出るまで進む．&lt;/p>
&lt;h3 id="ndkとcmakeのインストール">NDKとCMakeのインストール&lt;/h3>
&lt;p>More Actions &amp;gt; SDK Managerを開く．&lt;/p>
&lt;p>&lt;img src="http://blog.hirobon1690.com/post/eas-wsl/001.png"
width="737"
height="587"
srcset="http://blog.hirobon1690.com/post/eas-wsl/001_hu8f79635972b55704a75bfb17859fdb5e_48920_480x0_resize_box_3.png 480w, http://blog.hirobon1690.com/post/eas-wsl/001_hu8f79635972b55704a75bfb17859fdb5e_48920_1024x0_resize_box_3.png 1024w"
loading="lazy"
alt="スクリーンショット"
class="gallery-image"
data-flex-grow="125"
data-flex-basis="301px"
>&lt;/p>
&lt;p>SDK ToolsタブのNDKとCMakeにチェックを入れてApplyをクリック．&lt;/p>
&lt;p>&lt;img src="http://blog.hirobon1690.com/post/eas-wsl/002.png"
width="950"
height="732"
srcset="http://blog.hirobon1690.com/post/eas-wsl/002_huea855dd0c228d46de1fe9d7ba5267096_128782_480x0_resize_box_3.png 480w, http://blog.hirobon1690.com/post/eas-wsl/002_huea855dd0c228d46de1fe9d7ba5267096_128782_1024x0_resize_box_3.png 1024w"
loading="lazy"
alt="002"
class="gallery-image"
data-flex-grow="129"
data-flex-basis="311px"
>&lt;/p>
&lt;p>インストールが完了したらAndroid Studioを閉じて環境変数を設定する．&lt;code>~/.bashrc&lt;/code>に&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="nb">export&lt;/span> &lt;span class="nv">ANDROID_HOME&lt;/span>&lt;span class="o">=&lt;/span>/home/username/Android/Sdk
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>を追記する（&lt;code>username&lt;/code>は自分のもの）．&lt;/p>
&lt;h3 id="ビルド">ビルド&lt;/h3>
&lt;p>プロジェクトの&lt;code>eas.json&lt;/code>で&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;span class="lnt">9
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-json" data-lang="json">&lt;span class="line">&lt;span class="cl">&lt;span class="s2">&amp;#34;build&amp;#34;&lt;/span>&lt;span class="err">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="err">...&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;preview&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;distribution&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;internal&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;android&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;buildType&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;apk&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>&lt;span class="err">,&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>のように&lt;code>buildType&lt;/code>を指定する．&lt;br>
あとはプロジェクトのディレクトリで&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">eas build --platform android --profile preview --local
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>とするとビルドが通って&lt;code>.apk&lt;/code>が生成されると思います．&lt;/p>
&lt;div class="footnotes" role="doc-endnotes">
&lt;hr>
&lt;ol>
&lt;li id="fn:1">
&lt;p>ネイティブWindowsでAndroidのビルドは2023年1月時点では対応していない&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;/ol>
&lt;/div></description></item><item><title>ROS x GUIの備忘録</title><link>http://blog.hirobon1690.com/post/ros-gui/</link><pubDate>Wed, 03 Jan 2024 00:00:00 +0900</pubDate><guid>http://blog.hirobon1690.com/post/ros-gui/</guid><description>&lt;img src="http://blog.hirobon1690.com/post/ros-gui/image.png" alt="Featured image of post ROS x GUIの備忘録" />&lt;h2 id="about">About&lt;/h2>
&lt;p>&lt;a class="link" href="https://github.com/KeioRoboticsAssociation/hi_gui_app" target="_blank" rel="noopener"
>こういうことをした&lt;/a>ので，やったことをメモしておく．&lt;/p>
&lt;p>&lt;img src="http://blog.hirobon1690.com/post/ros-gui/image.png"
width="2778"
height="1940"
srcset="http://blog.hirobon1690.com/post/ros-gui/image_hub227ca672b1b939ab98a875ba666efae_1003551_480x0_resize_box_3.png 480w, http://blog.hirobon1690.com/post/ros-gui/image_hub227ca672b1b939ab98a875ba666efae_1003551_1024x0_resize_box_3.png 1024w"
loading="lazy"
alt="スクリーンショット"
class="gallery-image"
data-flex-grow="143"
data-flex-basis="343px"
>&lt;/p>
&lt;p>&lt;a class="link" href="https://hi-gui.web.app/" target="_blank" rel="noopener"
>デモURL&lt;/a>&lt;br>
部内Wikiに投稿した内容のほぼまんまである．大目に見てください&lt;/p>
&lt;h2 id="なにがしたいのか">なにがしたいのか&lt;/h2>
&lt;p>思想として，&lt;/p>
&lt;ol>
&lt;li>ROS側に指令値を送信できること&lt;/li>
&lt;li>ROS側の状態をreactiveに可視化できること&lt;/li>
&lt;li>iPadの特性をできるだけ活かしたUI設計にすること&lt;/li>
&lt;li>UIのフロント部分を簡潔かつ簡単に記述できること&lt;/li>
&lt;/ol>
&lt;p>の4点があった．ROSを組み込む場合におけるGUIの開発では，&lt;/p>
&lt;ul>
&lt;li>Linuxネイティブ&lt;sup id="fnref:1">&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref">1&lt;/a>&lt;/sup>
&lt;ul>
&lt;li>GTK3&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>マルチプラットフォーム（PC）
&lt;ul>
&lt;li>Qt&lt;/li>
&lt;li>Pythonを用いた様々（tkinter, simpleGUI, niceGUI, etc)&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>マルチプラットフォーム（PC, モバイル）
&lt;ul>
&lt;li>Web（Electron含む）&lt;/li>
&lt;li>Unity&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>モバイルプラットフォーム&lt;sup id="fnref:2">&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref">2&lt;/a>&lt;/sup>
&lt;ul>
&lt;li>Kotlin (Android)&lt;/li>
&lt;li>Java (Android)&lt;/li>
&lt;li>Swift (iOS)&lt;/li>
&lt;li>Objective-C (iOS) &lt;sup id="fnref:3">&lt;a href="#fn:3" class="footnote-ref" role="doc-noteref">3&lt;/a>&lt;/sup>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;p>が定石であろう．今回はiPadで操作できるという条件があったのと，メンテナンス性及び学習コストの観点からWebを選択した．&lt;/p>
&lt;h2 id="pros--cons">Pros &amp;amp; Cons&lt;/h2>
&lt;h3 id="webの何がいいか">Webの何がいいか&lt;/h3>
&lt;ul>
&lt;li>開発がしやすい
&lt;ul>
&lt;li>ベースがHTMLなのでデザイン系はほんとうにどうにでもなる&lt;/li>
&lt;li>フレームワークと合わせることでバックエンドのことは気にしなくてもよくなる&lt;/li>
&lt;li>「GUIの開発あるある」の面倒事が一切ない
&lt;ul>
&lt;li>謎のGUIエディタでゴニョゴニョするとか&lt;/li>
&lt;li>イベント駆動めんどくせーとか&lt;/li>
&lt;li>ビルドおっもとか&lt;/li>
&lt;li>そういうのがゼロ&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>ホットリロードがラク
&lt;ul>
&lt;li>後述&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>驚異のマルチプラットフォーム性
&lt;ul>
&lt;li>ブラウザさえあればどんなデバイスでも動く
&lt;ul>
&lt;li>罠はあるが&lt;/li>
&lt;li>Google Pixel Watchでもうごきましたよ()&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>テンションが上がる
&lt;ul>
&lt;li>思ったUIを思ったとおりにつくれる(小並感)
&lt;ul>
&lt;li>笑った？でも大事よこういうの&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h3 id="何がだめか">何がだめか&lt;/h3>
&lt;ul>
&lt;li>ROS側の起動などがやや面倒くさい
&lt;ul>
&lt;li>ROSbridge Serverなどを起動しなければならない&lt;/li>
&lt;li>接続に失敗した場合サーバの再起動など煩雑な手間が必要となる&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>接続の信頼性がネイティブUIよりも低い
&lt;ul>
&lt;li>ネイティブでUIを構築した場合にはない処理が行われたときの信頼性が大幅に劣る
&lt;ul>
&lt;li>ブラウザ上でのリロード&lt;/li>
&lt;li>回線が切断されてからの再接続&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>簡単な処理ならPythonで組んだほうがラク
&lt;ul>
&lt;li>という説もある．俺はTkinter特有の書き方があまり得意ではないので人によると思う&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h2 id="使用技術の選定">使用技術の選定&lt;/h2>
&lt;p>というワケで，賛否両論はあると思うがGUIをWebで構築することに踏み切った．今回使用した技術が以下の通り．&lt;/p>
&lt;h4 id="ros関連">ROS関連&lt;/h4>
&lt;ul>
&lt;li>&lt;a class="link" href="https://github.com/RobotWebTools/rosbridge_suite" target="_blank" rel="noopener"
>rosbridge_suite&lt;/a>&lt;/li>
&lt;li>&lt;a class="link" href="https://github.com/RobotWebTools/roslibjs" target="_blank" rel="noopener"
>roslibjs&lt;/a>&lt;/li>
&lt;/ul>
&lt;h4 id="web関連">Web関連&lt;/h4>
&lt;ul>
&lt;li>&lt;a class="link" href="https://react.dev/" target="_blank" rel="noopener"
>React&lt;/a>&lt;/li>
&lt;li>&lt;a class="link" href="https://vitejs.dev/" target="_blank" rel="noopener"
>Vite&lt;/a>&lt;/li>
&lt;li>&lt;a class="link" href="https://mui.com/" target="_blank" rel="noopener"
>mui&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>やりたいことは以下のような感じである．&lt;/p>
&lt;p>&lt;img src="http://blog.hirobon1690.com/post/ros-gui/002.jpg"
width="6910"
height="2820"
srcset="http://blog.hirobon1690.com/post/ros-gui/002_huc8dd876172758c362556d8267a682a8a_365235_480x0_resize_q75_box.jpg 480w, http://blog.hirobon1690.com/post/ros-gui/002_huc8dd876172758c362556d8267a682a8a_365235_1024x0_resize_q75_box.jpg 1024w"
loading="lazy"
alt="通信のイメージ"
class="gallery-image"
data-flex-grow="245"
data-flex-basis="588px"
>&lt;/p>
&lt;h2 id="ros側">ROS側&lt;/h2>
&lt;p>&lt;a class="link" href="https://robotwebtools.github.io/" target="_blank" rel="noopener"
>Robot Web Tools&lt;/a>様が偉大なる仕事をしてくださっているおかげで我々がすることは&lt;strong>rosbridge_serverを起動すること&lt;/strong>だけである．したがって&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">sudo apt install -y ros-humble-rosbridge-suite
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ros2 launch rosbridge_server rosbridge_websocket_launch.xml
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>以上である．&lt;/p>
&lt;h2 id="web側の実装">Web側の実装&lt;/h2>
&lt;p>ここから実装していくわけだが，備忘録兼チュートリアル記事ということなので簡単に「topicをpubするボタン」と「subした値をreactiveに表示する部分」の2つに絞って書き方の雛形的なものをここに残しておく．&lt;/p>
&lt;h3 id="依存関係のインストール">依存関係のインストール&lt;/h3>
&lt;p>まずは依存環境をインストールする．以下のスクリプトで最速で最新安定版のnodejsをインストールできる．&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">sudo apt update
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo apt install -y nodejs npm
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo npm -g install n
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo n stable
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo apt purge nodejs npm
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo apt autoremove
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>viteでプロジェクトをつくる．ROSと深く関連付けて管理する場合は適当にROSのパッケージを作成しその中などでやるといいと思う．&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">npm create vite@latest
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>とすると色々聞かれるので，プロジェクト名を入力し，その後Reactを選択:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">? Select a framework: » - Use arrow-keys. Return to submit.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> Vanilla
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> Vue
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;gt; React
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> Preact
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> Lit
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> Svelte
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> Solid
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> Qwik
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> Others
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>TypeScriptを選択:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">? Select a variant: » - Use arrow-keys. Return to submit.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;gt; TypeScript
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> TypeScript + SWC
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> JavaScript
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> JavaScript + SWC
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>するとよい．&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="nb">cd&lt;/span> プロジェクト名
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">npm i
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>で依存関係がインストールされる．&lt;br>
その後はUIフレームワークのmuiをインストールするために&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">npm install @mui/material @emotion/react @emotion/styled
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>とする．&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">npm run dev
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>して表示されたlocal IPをブラウザで開き，正常に画面が表示されることを確認できたら&lt;code>App.tsx&lt;/code>の内容を&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-tsx" data-lang="tsx">&lt;span class="line">&lt;span class="cl">&lt;span class="kr">import&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="nx">useState&lt;/span> &lt;span class="p">}&lt;/span> &lt;span class="kr">from&lt;/span> &lt;span class="s1">&amp;#39;react&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kr">import&lt;/span> &lt;span class="s1">&amp;#39;./App.css&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kd">function&lt;/span> &lt;span class="nx">App() {&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">&amp;lt;&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">&amp;lt;/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kr">export&lt;/span> &lt;span class="k">default&lt;/span> &lt;span class="nx">App&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>ここまで減らしてよい．&lt;/p>
&lt;h3 id="前提知識">前提知識&lt;/h3>
&lt;p>Reactの諸々はここでは省く．&lt;a class="link" href="https://ja.react.dev/learn" target="_blank" rel="noopener"
>よさげな日本語のチュートリアル&lt;/a>を見つけたので各自参照されたい．&lt;/p>
&lt;h3 id="rosオブジェクトの生成">ROSオブジェクトの生成&lt;/h3>
&lt;p>上の方で&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-tsx" data-lang="tsx">&lt;span class="line">&lt;span class="cl">&lt;span class="kr">import&lt;/span> &lt;span class="nx">ROSLIB&lt;/span> &lt;span class="kr">from&lt;/span> &lt;span class="s2">&amp;#34;roslib&amp;#34;&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kr">const&lt;/span> &lt;span class="nx">ros&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">new&lt;/span> &lt;span class="nx">ROSLIB&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">Ros&lt;/span>&lt;span class="p">({&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">url&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;ws://[ROSを走らせるPCのローカルIP]:9090&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">});&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>として&lt;code>ros&lt;/code>インスタンスを生成しておく．&lt;/p>
&lt;h3 id="topicのpub">TopicのPub&lt;/h3>
&lt;p>基本的には&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-tsx" data-lang="tsx">&lt;span class="line">&lt;span class="cl">&lt;span class="kr">const&lt;/span> &lt;span class="nx">Topic&lt;/span>&lt;span class="err">のインスタンス名&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">new&lt;/span> &lt;span class="nx">ROSLIB&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">Topic&lt;/span>&lt;span class="p">({&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">ros&lt;/span>: &lt;span class="kt">ros&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">name&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;/Topic名&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">messageType&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;Topicの型&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">});&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>としてTopicをインスタンス化する．例えば&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-tsx" data-lang="tsx">&lt;span class="line">&lt;span class="cl">&lt;span class="kr">const&lt;/span> &lt;span class="nx">msg&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">new&lt;/span> &lt;span class="nx">ROSLIB&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">Topic&lt;/span>&lt;span class="p">({&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">ros&lt;/span>: &lt;span class="kt">ros&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">name&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;/msg&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">messageType&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;std_msgs/String&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">});&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>といった形である．これを&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-tsx" data-lang="tsx">&lt;span class="line">&lt;span class="cl">&lt;span class="kd">function&lt;/span> &lt;span class="nx">App() {&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kr">const&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="nx">message&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">setMessage&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nx">useState&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kr">const&lt;/span> &lt;span class="nx">handleClick&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">()&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kr">const&lt;/span> &lt;span class="nx">msg&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">new&lt;/span> &lt;span class="nx">ROSLIB&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">Message&lt;/span>&lt;span class="p">({&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">data&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;hello, world&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">});&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">topic&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">publish&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">msg&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">setMessage&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;sent&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">&amp;lt;&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">button&lt;/span> &lt;span class="na">onClick&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="nx">handleClick&lt;/span>&lt;span class="p">}&amp;gt;&lt;/span>&lt;span class="nx">PUBLISH&lt;/span>&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">button&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>&lt;span class="nx">msg&lt;/span>&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">&amp;lt;/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>とすると&lt;strong>押すとPubするボタン&lt;/strong>の完成である．簡単でしょ？&lt;/p>
&lt;h3 id="topicのsub">TopicのSub&lt;/h3>
&lt;p>ROSのsubという仕組みとReactのreactive componentの相性は最高である．以下のように書くと&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-tsx" data-lang="tsx">&lt;span class="line">&lt;span class="cl">&lt;span class="kd">function&lt;/span> &lt;span class="nx">App() {&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kr">const&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="nx">msg&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">setMsg&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nx">useState&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">useEffect&lt;/span>&lt;span class="p">(()&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kr">const&lt;/span> &lt;span class="nx">listener&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">new&lt;/span> &lt;span class="nx">ROSLIB&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">Topic&lt;/span>&lt;span class="p">({&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">ros&lt;/span>: &lt;span class="kt">ros&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">name&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;/topic名&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">messageType&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;topicの型&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">});&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">listener&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">subscribe&lt;/span>&lt;span class="p">((&lt;/span>&lt;span class="nx">message&lt;/span>: &lt;span class="kt">any&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">setMsg&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">messsage&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">data&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">]);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">});&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span> &lt;span class="p">[]);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">&amp;lt;&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>&lt;span class="nx">msg&lt;/span>&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">&amp;lt;/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>指定したtopicをsubすると表示に反映されるようになる．&lt;/p>
&lt;h4 id="exercise">Exercise&lt;/h4>
&lt;p>topicをpubするボタンとそのtopicをsubするボタンをつくり，pubしたtopicの内容が反映されることを確認せよ．pubする内容をフォームなどを用いてreactiveに変化させるとなおよい．&lt;/p>
&lt;details>&lt;summary>解答例&lt;/summary>&lt;div>
略
&lt;/div>&lt;/details>
&lt;h3 id="おまけ---ios-safari向けのもろもろ">おまけ - iOS Safari向けのもろもろ&lt;/h3>
&lt;h4 id="画面全体のスクロール禁止">画面全体のスクロール禁止&lt;/h4>
&lt;p>どこから持ってきたか忘れてしまったが，&lt;code>ScrollLock.tsx&lt;/code>を作成して&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-tsx" data-lang="tsx">&lt;span class="line">&lt;span class="cl">&lt;span class="kr">import&lt;/span> &lt;span class="nx">React&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="nx">useEffect&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">useCallback&lt;/span> &lt;span class="p">}&lt;/span> &lt;span class="kr">from&lt;/span> &lt;span class="s2">&amp;#34;react&amp;#34;&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kr">const&lt;/span> &lt;span class="nx">ScrollLock&lt;/span>&lt;span class="o">=&lt;/span> &lt;span class="nx">React&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">memo&lt;/span>&lt;span class="p">(()&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">useEffect&lt;/span>&lt;span class="p">(()&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">document&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">addEventListener&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;touchmove&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">scrollNo&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="nx">passive&lt;/span>: &lt;span class="kt">false&lt;/span> &lt;span class="p">});&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="p">()&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">document&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">removeEventListener&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;touchmove&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">scrollNo&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span> &lt;span class="p">[]);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kr">const&lt;/span> &lt;span class="nx">scrollNo&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nx">useCallback&lt;/span>&lt;span class="p">((&lt;/span>&lt;span class="nx">e&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="nx">preventDefault&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">()&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="k">void&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="p">})&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">e&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">preventDefault&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span> &lt;span class="p">[]);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="p">&amp;lt;&amp;gt;&amp;lt;/&amp;gt;;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">});&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kr">export&lt;/span> &lt;span class="k">default&lt;/span> &lt;span class="nx">ScrollLock&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>とし，任意の箇所で&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-tsx" data-lang="tsx">&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">ScrollLock&lt;/span> &lt;span class="p">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>を挿入するとその場所でのスクロールが禁止される．&lt;/p>
&lt;h4 id="フルスクリーンpwa化4">フルスクリーンPWA化&lt;sup id="fnref:4">&lt;a href="#fn:4" class="footnote-ref" role="doc-noteref">4&lt;/a>&lt;/sup>&lt;/h4>
&lt;p>&lt;code>src/index.html&lt;/code>の&lt;code>&amp;lt;head&amp;gt;&amp;lt;/head&amp;gt;&lt;/code>内に&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-html" data-lang="html">&lt;span class="line">&lt;span class="cl"> &lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">meta&lt;/span> &lt;span class="na">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;apple-mobile-web-app-capable&amp;#34;&lt;/span> &lt;span class="na">content&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;yes&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">meta&lt;/span> &lt;span class="na">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;apple-mobile-web-app-status-bar-style&amp;#34;&lt;/span> &lt;span class="na">content&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;black-translucent&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">meta&lt;/span> &lt;span class="na">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;apple-mobile-web-app-title&amp;#34;&lt;/span> &lt;span class="na">content&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;アプリ名&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">link&lt;/span> &lt;span class="na">rel&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;apple-touch-icon&amp;#34;&lt;/span> &lt;span class="na">href&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;/icon.png&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span> &lt;span class="c">&amp;lt;!--アイコン画像を指定--&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>としてやるとiPadのSafariで「ホーム画面に追加」したときの動作をアプリのようにすることができる．&lt;/p>
&lt;h3 id="ここからは">ここからは？&lt;/h3>
&lt;ul>
&lt;li>muiには&lt;a class="link" href="https://mui.com/material-ui/all-components/" target="_blank" rel="noopener"
>様々なコンポーネント&lt;/a>があるため様々なWeb的表現を駆使したUIをROSにつなぐことが可能である．&lt;/li>
&lt;li>&lt;a class="link" href="https://robotwebtools.github.io/" target="_blank" rel="noopener"
>Robot Web Tools&lt;/a>は他にも様々なWeb用ROSライブラリを提供しているため，UI上に3Dモデルを表示することなども可能である．
&lt;ul>
&lt;li>安定性は保証できないが&amp;hellip;&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h3 id="いかがでしたか">いかがでしたか？&lt;/h3>
&lt;p>(略)&lt;/p>
&lt;h3 id="参考文献">参考文献&lt;/h3>
&lt;ul>
&lt;li>&lt;a class="link" href="https://zenn.dev/tasada038/articles/90530ccec33619" target="_blank" rel="noopener"
>rosbridge_suiteとReactでROS 2 Webアプリを作る&lt;/a>&lt;br>
&lt;del>本記事は↑すばらしいこの記事↑の下位互換なのではないかという説がある&lt;/del>&lt;/li>
&lt;/ul>
&lt;div class="footnotes" role="doc-endnotes">
&lt;hr>
&lt;ol>
&lt;li id="fn:1">
&lt;p>ネイティブであるかどうかはそのディストリビューションのDesktop environmentに依存する．多くのUbuntuユーザはデフォルトであるGNOMEを用いていることからこのような表記を行っており，例えばKDEを用いているユーザにとってのネイティブツールキットはQtである．&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:2">
&lt;p>これらのプラットフォームにおいてはROSをネイティブサポートしていないため，必然的にWebインタフェースのフロントエンドとして振る舞わせることになる．&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:3">
&lt;p>iOS向けのアプリをビルドするにはmacOSを搭載したマシンが必要である．&amp;#160;&lt;a href="#fnref:3" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:4">
&lt;p>厳密にはPWAではないが，便宜上このような書き方をしている．&amp;#160;&lt;a href="#fnref:4" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;/ol>
&lt;/div></description></item><item><title>WindowsでX11 Port Fowarding</title><link>http://blog.hirobon1690.com/post/windows-x11/</link><pubDate>Mon, 10 Apr 2023 00:00:00 +0900</pubDate><guid>http://blog.hirobon1690.com/post/windows-x11/</guid><description>&lt;img src="http://blog.hirobon1690.com/post/windows-x11/002.png" alt="Featured image of post WindowsでX11 Port Fowarding" />&lt;h2 id="はじめに">はじめに&lt;/h2>
&lt;p>UNIX系のOSでは比較的簡単にX11の転送ができるのだが，Windowsだと少々手順が必要になったので備忘録としてまとめておく．&lt;br>
Windows TerminalとVSCodeそれぞれで設定する必要がある．&lt;/p>
&lt;h2 id="x11のインストール">X11のインストール&lt;/h2>
&lt;ol>
&lt;li>&lt;a class="link" href="https://sourceforge.net/projects/vcxsrv/" target="_blank" rel="noopener"
>VcXsrv&lt;/a>をインストールする．&lt;br>
&lt;style>
@media (prefers-color-scheme: dark) {
.box{
background-color: #5b5b5b;
}
}
.box{
width: 100%;
max-width: 500px;
height: 100px;
background-color: var(--link-card-background) !important;
color: var(--accent-color);
border-radius: 10px;
overflow: hidden;
display: flex!important;
vertical-align: top!important;
box-shadow: 0 0 5px 1px rgba(0, 0, 0, .2);
}
.box:hover{
opacity: 0.8;
}
.text{
margin: 5px 0 0 10px;
}
.img-class {
width: 100px;
height: 100px!important;
object-fit: cover;
}
.url{
font-size: smaller;
color: lightgray;
margin: 0 0 0 10px;
color: var(--accent-color-darker);
}
.flex{
display: flex;
}
&lt;/style>
&lt;a class='flex' href="https://sourceforge.net/projects/vcxsrv/" target="_blank" rel="noopener noreferrer">
&lt;div class='box'>
&lt;img src="" class='img-class'>
&lt;div>
&lt;p class='text'>VcXsrv Windows X Server&lt;/p>
&lt;p class='url'>https://sourceforge.net/projects/vcxsrv/&lt;/p>
&lt;/div>
&lt;/div>
&lt;/a>&lt;/li>
&lt;li>XLaunchを起動し，X Serverを裏で走らせておく．&lt;/li>
&lt;/ol>
&lt;h2 id="windows-terminalの設定">Windows Terminalの設定&lt;/h2>
&lt;ol>
&lt;li>PowerShellを開いて環境変数を設定する．&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-pwsh" data-lang="pwsh">&lt;span class="line">&lt;span class="cl">&lt;span class="nv">$env:DISPLAY&lt;/span>&lt;span class="p">=&lt;/span>&lt;span class="s2">&amp;#34;127.0.0.1:0.0&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;ol>
&lt;li>接続時に &lt;code>-Y&lt;/code> オプションを付ける．&lt;br>
例&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-pwsh" data-lang="pwsh">&lt;span class="line">&lt;span class="cl">&lt;span class="n">ssh&lt;/span> &lt;span class="n">userName&lt;/span>&lt;span class="nv">@hostName&lt;/span> &lt;span class="n">-Y&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="追記">追記&lt;/h3>
&lt;p>cannot open displayとなるときは&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">sudo apt install -y xauth
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>するとよい．&lt;/p>
&lt;h2 id="vscodeの設定">VSCodeの設定&lt;/h2>
&lt;ol>
&lt;li>
&lt;p>対象のホストに1度SSH接続しておき，configファイルを作成しておく．&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;code>F1&lt;/code>を押して&lt;code>ssh&lt;/code>などで検索し「Remote:SSH SSH 構成ファイルを開く&amp;hellip;」を選択する&lt;/p>
&lt;p>&lt;img src="http://blog.hirobon1690.com/post/windows-x11/001.png"
width="751"
height="113"
srcset="http://blog.hirobon1690.com/post/windows-x11/001_hu5a89075a2842d7a53ce03f578f231a41_16920_480x0_resize_box_3.png 480w, http://blog.hirobon1690.com/post/windows-x11/001_hu5a89075a2842d7a53ce03f578f231a41_16920_1024x0_resize_box_3.png 1024w"
loading="lazy"
alt="選択"
class="gallery-image"
data-flex-grow="664"
data-flex-basis="1595px"
>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>X11フォワーディングを使用したいホストを，以下のように編集する．&lt;/p>
&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">Host hostname
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> HostName hostname
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> User usename
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ForwardX11 yes
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ForwardX11Trusted yes
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="結果">結果&lt;/h2>
&lt;p>sshのターミナルで&lt;code>xeyes&lt;/code>を実行した結果が以下．&lt;/p>
&lt;p>&lt;img src="http://blog.hirobon1690.com/post/windows-x11/002.png"
width="382"
height="295"
srcset="http://blog.hirobon1690.com/post/windows-x11/002_hu5cb33b7f78c141967c7801145cacc367_5952_480x0_resize_box_3.png 480w, http://blog.hirobon1690.com/post/windows-x11/002_hu5cb33b7f78c141967c7801145cacc367_5952_1024x0_resize_box_3.png 1024w"
loading="lazy"
alt="xeyesが起動している様子"
class="gallery-image"
data-flex-grow="129"
data-flex-basis="310px"
>&lt;/p></description></item><item><title>【備忘録】FBXモーションをBVHに変換してMMDに持っていく</title><link>http://blog.hirobon1690.com/post/fbx-to-vmd/</link><pubDate>Sat, 11 Feb 2023 00:00:00 +0900</pubDate><guid>http://blog.hirobon1690.com/post/fbx-to-vmd/</guid><description>&lt;img src="http://blog.hirobon1690.com/post/fbx-to-vmd/003.png" alt="Featured image of post 【備忘録】FBXモーションをBVHに変換してMMDに持っていく" />&lt;p>3DCG系のプロジェクトを進めており，モーションを購入した．&lt;/p>
&lt;p>モーションキャプチャで収録したデータが，FBX形式で入っている．&lt;br>
特になんの知識もなかったので，適当にポンっとやればMMDモデルで動かせると思っていたが，現実は甘くなかった．&lt;br>
Live Animationというツールを使う方法や，AutoRigProを使ってBlenderでリターゲットする方法などがあることが判明したが，どれも自分の思うようにいかなかった．&lt;br>
丸3日費やして方法を見つけたので，メモしておく．&lt;/p>
&lt;h2 id="0-流れ">0. 流れ&lt;/h2>
&lt;p>FBX → BVH をBlenderで行う&lt;br>
BVHの座標軸をBlenderで修正する&lt;br>
BVH → VMD を有志ツール(後述)で行う&lt;/p>
&lt;h2 id="1-fbxbvh">1. FBX→BVH&lt;/h2>
&lt;p>まずはBlenderにFBXを読み込む．&lt;strong>が&lt;/strong>，標準の読み込み機能ではなぜかボーンの向きがひっちゃかめっちゃかになってしまう．&lt;/p>
&lt;p>&lt;img src="http://blog.hirobon1690.com/post/fbx-to-vmd/001.png"
width="603"
height="695"
srcset="http://blog.hirobon1690.com/post/fbx-to-vmd/001_hu6705b9f64347f747f43dcf954fa500c6_111872_480x0_resize_box_3.png 480w, http://blog.hirobon1690.com/post/fbx-to-vmd/001_hu6705b9f64347f747f43dcf954fa500c6_111872_1024x0_resize_box_3.png 1024w"
loading="lazy"
alt="腕の向きがおかしい"
class="gallery-image"
data-flex-grow="86"
data-flex-basis="208px"
>&lt;/p>
&lt;p>埒が明かないので，有料アドオンを購入した．こちらでは正常に読み込める．&lt;br>
failed to fetch remote resource: Forbidden&lt;/p>
&lt;p>&lt;img src="http://blog.hirobon1690.com/post/fbx-to-vmd/002.png"
width="741"
height="710"
srcset="http://blog.hirobon1690.com/post/fbx-to-vmd/002_huf631a3ede6191e261da20b9013537cc6_126297_480x0_resize_box_3.png 480w, http://blog.hirobon1690.com/post/fbx-to-vmd/002_huf631a3ede6191e261da20b9013537cc6_126297_1024x0_resize_box_3.png 1024w"
loading="lazy"
alt="正常に読み込めた"
class="gallery-image"
data-flex-grow="104"
data-flex-basis="250px"
>&lt;/p>
&lt;p>Blenderくん，頼むよ&amp;hellip;&lt;/p>
&lt;p>読み込めたら，&lt;code>ファイル&lt;/code>&amp;gt;&lt;code>エクスポート&lt;/code>&amp;gt;&lt;code>bvh&lt;/code>から書き出す．&lt;/p>
&lt;h2 id="2-bvhの座標軸の修正">2. BVHの座標軸の修正&lt;/h2>
&lt;p>Blenderは上がZの右手系なのに対し，MMDは上がYの右手系であるため，データを回転する必要がある．&lt;br>
&lt;code>ファイル&lt;/code>&amp;gt;&lt;code>インポート &lt;/code>&amp;gt;&lt;code>bvh&lt;/code>のウィンドウの右側の&lt;code>トランスフォーム&lt;/code>の欄を以下のように変更する．&lt;/p>
&lt;p>&lt;img src="http://blog.hirobon1690.com/post/fbx-to-vmd/004.png"
width="301"
height="203"
srcset="http://blog.hirobon1690.com/post/fbx-to-vmd/004_hu71282bd0703c1da8bc5902ada4c43242_11673_480x0_resize_box_3.png 480w, http://blog.hirobon1690.com/post/fbx-to-vmd/004_hu71282bd0703c1da8bc5902ada4c43242_11673_1024x0_resize_box_3.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="148"
data-flex-basis="355px"
>&lt;/p>
&lt;p>読み込んだら，FBXのときと同様の手順で再度BVHにエクスポートする．&lt;/p>
&lt;h2 id="3-bvhvmd">3. BVH→VMD&lt;/h2>
&lt;p>&lt;a class="link" href="https://6i9.booth.pm/" target="_blank" rel="noopener"
>ゆきときプロジェクト&lt;/a>様の&lt;a class="link" href="https://booth.pm/ja/items/3242387" target="_blank" rel="noopener"
>BVH to VMD Converter&lt;/a>を使わせていただく．&lt;br>
&lt;style>
@media (prefers-color-scheme: dark) {
.box{
background-color: #5b5b5b;
}
}
.box{
width: 100%;
max-width: 500px;
height: 100px;
background-color: var(--link-card-background) !important;
color: var(--accent-color);
border-radius: 10px;
overflow: hidden;
display: flex!important;
vertical-align: top!important;
box-shadow: 0 0 5px 1px rgba(0, 0, 0, .2);
}
.box:hover{
opacity: 0.8;
}
.text{
margin: 5px 0 0 10px;
}
.img-class {
width: 100px;
height: 100px!important;
object-fit: cover;
}
.url{
font-size: smaller;
color: lightgray;
margin: 0 0 0 10px;
color: var(--accent-color-darker);
}
.flex{
display: flex;
}
&lt;/style>
&lt;a class='flex' href="https://booth.pm/ja/items/3242387" target="_blank" rel="noopener noreferrer">
&lt;div class='box'>
&lt;img src="http://blog.hirobon1690.com/_hu2b6ad5d205500bd28f4528a2b27e1b61_0_c584b4a660e30b3e95c0cb07ead72891.webp" class='img-class'>
&lt;div>
&lt;p class='text'>【無料】BVH to VMD Converter&lt;/p>
&lt;p class='url'>https://booth.pm/ja/items/3242387&lt;/p>
&lt;/div>
&lt;/div>
&lt;/a>&lt;/p>
&lt;p>このツールには以下の3つの機能がある:&lt;/p>
&lt;h4 id="1-ボーン名の変換">1. ボーン名の変換&lt;/h4>
&lt;p>対照表に従い，BVHのボーン名をMMDのボーン名に変換する&lt;/p>
&lt;h4 id="2-角度補正">2. 角度補正&lt;/h4>
&lt;p>(未検証，ミリしらで書いてる)BVHはTポーズからの相対角度，VMDはAポーズからの相対角度でモーションを記録しているっぽい．オフセットを設定することでこの角度差を補正できる．&lt;/p>
&lt;h4 id="3-vmdへの変換">3. VMDへの変換&lt;/h4>
&lt;p>上の2つの変換を施した上で，VMDに変換してくれる&lt;/p>
&lt;p>まさに神ツール．ありがとうございます．&lt;/p>
&lt;p>ボーンマップに今回のボーン名がないため，手動で追記する．追記した&lt;code>AutoBoneMap.csv&lt;/code>を&lt;a class="link" href="./AutoBoneMap.csv" >ここ&lt;/a>に置いておくので，自己責任で使ってください．&lt;/p>
&lt;p>&lt;code>Convert&lt;/code>をクリックすると変換される．&lt;/p>
&lt;p>&lt;img src="http://blog.hirobon1690.com/post/fbx-to-vmd/005.png"
width="941"
height="621"
srcset="http://blog.hirobon1690.com/post/fbx-to-vmd/005_hu61b932d632408e26e1cec0fdbae42191_199978_480x0_resize_box_3.png 480w, http://blog.hirobon1690.com/post/fbx-to-vmd/005_hu61b932d632408e26e1cec0fdbae42191_199978_1024x0_resize_box_3.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="151"
data-flex-basis="363px"
>&lt;/p>
&lt;h2 id="4-mmdで読み込む">4. MMDで読み込む&lt;/h2>
&lt;p>出力した&lt;code>vmd&lt;/code>ファイルをMMDで読み込むと，モーションが反映されると思う．もし向きや角度がおかしかったら，2の座標軸を見直したり，3のcsvのオフセット値を変えてみたりすると良いだろう．また，足のIKをオフにする必要があるので注意．&lt;/p></description></item><item><title>Autodesk EAGLE 9系でスケーリングの問題を解消する(Windows)</title><link>http://blog.hirobon1690.com/post/fix-eagle-scaling/</link><pubDate>Sat, 11 Feb 2023 00:00:00 +0900</pubDate><guid>http://blog.hirobon1690.com/post/fix-eagle-scaling/</guid><description>&lt;img src="http://blog.hirobon1690.com/post/fix-eagle-scaling/fig0.png" alt="Featured image of post Autodesk EAGLE 9系でスケーリングの問題を解消する(Windows)" />&lt;p>解像度が高いパソコンを使用しているとき，通常WindowsはOSレベルで画面をスケーリングして拡大表示している．EAGLEではここ周りの処理に不具合が残っており，普通に起動するだけではおかしな表示になってしまう．&lt;/p>
&lt;p>&lt;img src="http://blog.hirobon1690.com/post/fix-eagle-scaling/fig0.png"
width="1813"
height="1080"
srcset="http://blog.hirobon1690.com/post/fix-eagle-scaling/fig0_hu77afae94a5c4fb9e0eaf755494d804f3_399339_480x0_resize_box_3.png 480w, http://blog.hirobon1690.com/post/fix-eagle-scaling/fig0_hu77afae94a5c4fb9e0eaf755494d804f3_399339_1024x0_resize_box_3.png 1024w"
loading="lazy"
alt="メモ帳のテキストサイズと比べるとそのおかしさがわかる"
class="gallery-image"
data-flex-grow="167"
data-flex-basis="402px"
>&lt;/p>
&lt;h2 id="解決策">解決策&lt;/h2>
&lt;p>EAGLEは9系からQtというUIフレームワークを使用するようになった．Qtのスケール設定をこちらから明示してあげることで正しい大きさで表示されるようになる．&lt;/p>
&lt;h3 id="1-eagle側の設定">1. EAGLE側の設定&lt;/h3>
&lt;p>&lt;code>Options &amp;gt; User Interface &amp;gt; Display &amp;gt; Enable...&lt;/code> の2つのチェックを外す．&lt;/p>
&lt;p>&lt;img src="http://blog.hirobon1690.com/post/fix-eagle-scaling/fig1.png"
width="4148"
height="2475"
srcset="http://blog.hirobon1690.com/post/fix-eagle-scaling/fig1_hucefd01b36fb430cce944998a4c3b28cc_2946878_480x0_resize_box_3.png 480w, http://blog.hirobon1690.com/post/fix-eagle-scaling/fig1_hucefd01b36fb430cce944998a4c3b28cc_2946878_1024x0_resize_box_3.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="167"
data-flex-basis="402px"
>&lt;/p>
&lt;h3 id="2-バッチファイルを作成">2. バッチファイルを作成&lt;/h3>
&lt;p>以下の内容でバッチファイルを作成する．&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-batchfile" data-lang="batchfile">&lt;span class="line">&lt;span class="cl">&lt;span class="p">@&lt;/span>&lt;span class="k">echo&lt;/span> off
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">cd&lt;/span> [EAGLEのディレクトリ]
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">set&lt;/span> &lt;span class="nv">QT_SCALE_FACTOR&lt;/span>&lt;span class="p">=&lt;/span>1.5
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">START&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span> eagle.exe
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>※1 [EAGLEのディレクトリ]にはeagle.exeがインストールされているフォルダを選択する．&lt;br>
デフォルトでは&lt;code>C:\EAGLE 9.6.2&lt;/code>&lt;/p>
&lt;p>※2 &amp;ldquo;1.5&amp;rdquo; の部分はお使いのスケーリング係数に合わせる．これはWindowsの設定アプリのディスプレイの項目から確認できる．(100%が1)&lt;/p>
&lt;p>このバッチファイルを&lt;code>eagle.bat&lt;/code>として保存してEAGLEのディレクトリに移動する．&lt;/p>
&lt;h3 id="3-ショートカットに登録">3. ショートカットに登録&lt;/h3>
&lt;ol>
&lt;li>スタートメニューにあるEAGLEの項目を右クリックして「ファイルの場所を開く」を押す．&lt;/li>
&lt;li>EAGLEを右クリックして「プロパティ」を開く．&lt;/li>
&lt;li>「リンク先」の &lt;code>...\eagle.exe&lt;/code> を &lt;code>...\eagle.bat&lt;/code> に変更する．&lt;/li>
&lt;li>「実行時の大きさ」を「最小化」にする．&lt;/li>
&lt;li>「アイコンの変更」を押してEAGLEのディレクトリに移動したあと，&lt;code>eagle.ico&lt;/code> を選択する．&lt;/li>
&lt;/ol>
&lt;p>&lt;img src="http://blog.hirobon1690.com/post/fix-eagle-scaling/fig2.png"
width="709"
height="987"
srcset="http://blog.hirobon1690.com/post/fix-eagle-scaling/fig2_hu107622c335cf51dd625d4b366772e6e0_100003_480x0_resize_box_3.png 480w, http://blog.hirobon1690.com/post/fix-eagle-scaling/fig2_hu107622c335cf51dd625d4b366772e6e0_100003_1024x0_resize_box_3.png 1024w"
loading="lazy"
alt="設定例"
class="gallery-image"
data-flex-grow="71"
data-flex-basis="172px"
>&lt;/p>
&lt;p>これで，スタートメニューから起動すると正しい大きさで起動できると思います．&lt;br>
&lt;style>
@media (prefers-color-scheme: dark) {
.box{
background-color: #5b5b5b;
}
}
.box{
width: 100%;
max-width: 500px;
height: 100px;
background-color: var(--link-card-background) !important;
color: var(--accent-color);
border-radius: 10px;
overflow: hidden;
display: flex!important;
vertical-align: top!important;
box-shadow: 0 0 5px 1px rgba(0, 0, 0, .2);
}
.box:hover{
opacity: 0.8;
}
.text{
margin: 5px 0 0 10px;
}
.img-class {
width: 100px;
height: 100px!important;
object-fit: cover;
}
.url{
font-size: smaller;
color: lightgray;
margin: 0 0 0 10px;
color: var(--accent-color-darker);
}
.flex{
display: flex;
}
&lt;/style>
&lt;a class='flex' href="https://www.amazon.co.jp/dp/B09YRXYSFK" target="_blank" rel="noopener noreferrer">
&lt;div class='box'>
&lt;img src="http://blog.hirobon1690.com/img/default_huf044c2fbafe082fc6235c0e83e8785d7_957_200x200_fill_q100_h2_box_center_3.webp" class='img-class'>
&lt;div>
&lt;p class='text'>Amazon.co.jp: DiyStudio 5pc 5A dc-dc降圧ブーストコンバータ調整可能レギュレータXL4015 4-38Vから1.25-36V出力調整可能降圧ボードモジュール調整電源変換ボード降圧ボード高効率低リップル電源アダプタ基板降 圧回路基板 【ヒートシンク付き】 : 産業・研究開発用品&lt;/p>
&lt;p class='url'>https://www.amazon.co.jp/dp/B09YRXYSFK&lt;/p>
&lt;/div>
&lt;/div>
&lt;/a>&lt;/p></description></item><item><title>About</title><link>http://blog.hirobon1690.com/page/about/</link><pubDate>Wed, 04 Jan 2023 00:00:00 +0900</pubDate><guid>http://blog.hirobon1690.com/page/about/</guid><description>&lt;p>hirobon1690のブログ&lt;br>
&lt;style>
@media (prefers-color-scheme: dark) {
.box{
background-color: #5b5b5b;
}
}
.box{
width: 100%;
max-width: 500px;
height: 100px;
background-color: var(--link-card-background) !important;
color: var(--accent-color);
border-radius: 10px;
overflow: hidden;
display: flex!important;
vertical-align: top!important;
box-shadow: 0 0 5px 1px rgba(0, 0, 0, .2);
}
.box:hover{
opacity: 0.8;
}
.text{
margin: 5px 0 0 10px;
}
.img-class {
width: 100px;
height: 100px!important;
object-fit: cover;
}
.url{
font-size: smaller;
color: lightgray;
margin: 0 0 0 10px;
color: var(--accent-color-darker);
}
.flex{
display: flex;
}
&lt;/style>
&lt;a class='flex' href="https://github.com/hirobon1690" target="_blank" rel="noopener noreferrer">
&lt;div class='box'>
&lt;img src="http://blog.hirobon1690.com/58695125_14829859978209304760_huccae29b4c42e23c4fb2e389c769fc4bb_0_200x200_fill_q100_h2_box_center.webp" class='img-class'>
&lt;div>
&lt;p class='text'>GitHub&lt;/p>
&lt;p class='url'>https://github.com/hirobon1690&lt;/p>
&lt;/div>
&lt;/div>
&lt;/a>&lt;br>
&lt;style>
@media (prefers-color-scheme: dark) {
.box{
background-color: #5b5b5b;
}
}
.box{
width: 100%;
max-width: 500px;
height: 100px;
background-color: var(--link-card-background) !important;
color: var(--accent-color);
border-radius: 10px;
overflow: hidden;
display: flex!important;
vertical-align: top!important;
box-shadow: 0 0 5px 1px rgba(0, 0, 0, .2);
}
.box:hover{
opacity: 0.8;
}
.text{
margin: 5px 0 0 10px;
}
.img-class {
width: 100px;
height: 100px!important;
object-fit: cover;
}
.url{
font-size: smaller;
color: lightgray;
margin: 0 0 0 10px;
color: var(--accent-color-darker);
}
.flex{
display: flex;
}
&lt;/style>
&lt;a class='flex' href="https://twitter.com/hirobon1690/" target="_blank" rel="noopener noreferrer">
&lt;div class='box'>
&lt;img src="http://blog.hirobon1690.com/icon-ios.77d25eba_14545805538075966193_hue90a819e9fd1a2bb8d19ba0649cef207_0_200x200_fill_q100_h2_box_center_3.webp" class='img-class'>
&lt;div>
&lt;p class='text'>Twitter&lt;/p>
&lt;p class='url'>https://twitter.com/hirobon1690/&lt;/p>
&lt;/div>
&lt;/div>
&lt;/a>&lt;/p>
&lt;h4 id="本ページではgoogle-analyticsを使用しています">本ページではGoogle Analyticsを使用しています．&lt;/h4></description></item><item><title>Hello, world!</title><link>http://blog.hirobon1690.com/post/hello-world/</link><pubDate>Wed, 04 Jan 2023 00:00:00 +0900</pubDate><guid>http://blog.hirobon1690.com/post/hello-world/</guid><description>&lt;p>ブログをはじめようはじめようと思って3年が経過しました．&lt;br>
今年こそは，と思ってひとまず環境を整えました．&lt;br>
続くか本当に不明ですが何卒よろしくお願いします．&lt;br>
製作記的な記事と備忘録がメインとなる予定です．（ほんまに？）&lt;/p>
&lt;style>
@media (prefers-color-scheme: dark) {
.box{
background-color: #5b5b5b;
}
}
.box{
width: 100%;
max-width: 500px;
height: 100px;
background-color: var(--link-card-background) !important;
color: var(--accent-color);
border-radius: 10px;
overflow: hidden;
display: flex!important;
vertical-align: top!important;
box-shadow: 0 0 5px 1px rgba(0, 0, 0, .2);
}
.box:hover{
opacity: 0.8;
}
.text{
margin: 5px 0 0 10px;
}
.img-class {
width: 100px;
height: 100px!important;
object-fit: cover;
}
.url{
font-size: smaller;
color: lightgray;
margin: 0 0 0 10px;
color: var(--accent-color-darker);
}
.flex{
display: flex;
}
&lt;/style>
&lt;a class='flex' href="https://github.com/hirobon1690" target="_blank" rel="noopener noreferrer">
&lt;div class='box'>
&lt;img src="http://blog.hirobon1690.com/58695125_14829859978209304760_huccae29b4c42e23c4fb2e389c769fc4bb_0_200x200_fill_q100_h2_box_center.webp" class='img-class'>
&lt;div>
&lt;p class='text'>GitHub&lt;/p>
&lt;p class='url'>https://github.com/hirobon1690&lt;/p>
&lt;/div>
&lt;/div>
&lt;/a></description></item><item><title>Archives</title><link>http://blog.hirobon1690.com/page/archives/</link><pubDate>Tue, 28 May 2019 00:00:00 +0900</pubDate><guid>http://blog.hirobon1690.com/page/archives/</guid><description/></item><item><title/><link>http://blog.hirobon1690.com/page/links/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://blog.hirobon1690.com/page/links/</guid><description/></item><item><title/><link>http://blog.hirobon1690.com/post/test/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://blog.hirobon1690.com/post/test/</guid><description/></item><item><title>Search</title><link>http://blog.hirobon1690.com/page/search/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://blog.hirobon1690.com/page/search/</guid><description/></item></channel></rss>