<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0"
  xmlns:atom="http://www.w3.org/2005/Atom"
  xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Hi 我劉昕</title>
    <link>https://shuaixin.cc/</link>
    
    <image>
      <url>https://shuaixin.cc/icon.png</url>
      <title>Hi 我劉昕</title>
      <link>https://shuaixin.cc/</link>
    </image>
    
    <atom:link href="https://shuaixin.cc/rss2.xml" rel="self" type="application/rss+xml"/>
    
    <description>劉昕的部落格</description>
    <pubDate>Sat, 09 May 2026 03:25:09 GMT</pubDate>
    <generator>http://hexo.io/</generator>
    
    <item>
      <title>槓精玩家的三合一人生格言</title>
      <link>https://shuaixin.cc/Trinity-Motto/</link>
      <guid>https://shuaixin.cc/Trinity-Motto/</guid>
      <pubDate>Thu, 07 May 2026 16:00:00 GMT</pubDate>
      
        
        
          
          
      <description></description>
          
        
      
      
      
      <content:encoded><![CDATA[<blockquote><p>這是我的「<a href="https://blogblog.club/party/">BlogBlog 同樂會 - 2026 年 5 月</a>」的投稿文章。本月主題是「<a href="https://eddielv.com/articles/a-sentence-changing-you/">改變人生觀的一句話</a>」，由 <a href="https://eddielv.com/">Eddie Lv</a> 主持。如果你有自己的部落格，歡迎一起來參加！</p></blockquote><p>我得先承認，我拿不出改變我人生觀的一句話。</p><p>倒不如說，在這期同樂會之前的很長一段時間之中，我就已經有在刻意地尋找一句屬於我的座右銘。因為我本來的 slogan 是——「努力的男人不一定最帥，但一定最累」，整個意義不明，除了讓人懷疑這傢伙有一定程度的外貌 issue 以外，沒傳遞其他的有效訊息，所以我想把它換掉。</p><p>然而撰文的當下，座右銘還沒想到，所以 slogan 還是同一句。</p><ul><li></li></ul><p>當然，slogan 跟座右銘並不指涉同一個概念。slogan 是外顯的，它本身具有向外傳播一個概念的任務。而座右銘則不一定，有時候它可以單純放在心裡，能拿來作為自己的行為指引就足矣。（或是走一個反骨路線放在座位左邊）</p><p>另一個思路是，我們<a href="https://club.1-know.org/">讀書會</a>有成員分享：「所有的痛苦都來自於身心不合一」。我在想，如果我的 slogan 跟座右銘是<strong>同一句</strong>，那是不是能幫助我自己更加地「身心合一」呢？</p><p>你猜怎麼著？我甚至在想，如果我<strong>連墓誌銘都是同一句</strong>，閣下覺得如何？這樣我不止「身心合一」，我還直接「以終為始」。</p><p>感覺不錯，接下來我要來試圖尋找集合了 slogan、座右銘、墓誌銘的三位一體的人生格言。</p><ul><li></li></ul><p>我在三月的投稿<a href="https://shuaixin.cc/Ideal-Life/">《理想的生活：差值外包之術》</a>中提到，人對世界的感知是基於差值的，所以這個人生格言它理想上應該要是「差值包容」的。否則我們的行為選擇會有偏食傾向，直到營養不良。</p><p>舉個例子，「但行好路，莫問前程」就我看來就不夠包容。雖然裡面的「好路」保留了一定程度的解釋空間，讓使用者自己定義所謂「好」，但我能不能「不走」呢？雖然我可能過於嚴格，有點槓精意味，但這句話隱含著你要一直「前進」的前提假設，不是嗎？偶爾用來鼓勵鼓勵自己還不錯，但若拿來用一輩子，怕是包容度不足。</p><p>Hmm… 照我這樣的篩選邏輯，大概是很難找到合適的句子了。感覺就算有，它也只會是一種模棱兩可的存在？畢竟只要有指導意味，就會被我說是沒有包容度；但沒有指導意味，它還有用嗎？</p><ul><li></li></ul><p>最近我們<a href="https://club.1-know.org/">讀書會</a><s>瀰漫著一股虛無主義的氛圍</s>對所謂人生的意義稍有討論，而這條路上，「看山不是山」確實是一個避不開的環節。看清了生活的真相之後（還真不是山），後面要怎麼繼續生活，就成了一個大哉問。而我們把有了這層認知、運用了後設思維看待諸相的人，稱呼為「玩家」。</p><p>成為玩家後，會遇到第一個問題就是——要玩什麼？身為一個新手玩家，這大概是我近些日子以來，縈繞在心中的一個課題吧。這挺有趣的，就像你初入一個開放世界的遊戲，給你的第一個任務不是肯定句，而是疑問句。</p><p>雖然玩家的比例高不高我不知道，但總數必定是可觀的。對於虛無主義這種玩家中常見的病症，早有流行的藥方，即存在主義。於是卡繆<sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup>的名言就成為了我心中的候選句子之一：</p><blockquote><p>我們必須想像薛西弗斯是幸福的。</p></blockquote><p>我們在想，薛西弗斯看山又是山了，對嗎？</p><ul><li></li></ul><p>老實說，我覺得「開心就好」很有潛力，它當 slogan 很有精神、當座右銘很通透、當墓誌銘很灑脫。然而，玩家甚至會去質疑「開心就好」這種皆大歡喜的命題。</p><p>受到<a href="https://e89295.com/blog/2026-04-04.html">這篇文章</a>的啟發，加上我最近在讀《機器人叛亂：在達爾文時代找到意義》，我們會問：開心就好？可是活著是為了快樂嗎？</p><p>如果我們不會說「活著是為了吃」（我們會說吃是為了活著），那為什麼我們會說「活著是為了快樂」呢？想吃東西跟想快樂都是原始的生物驅力，來自基因對我們進行的生存引導——會讓我們感到快樂的事打從一開始就是因為基因鼓勵我們做那些事。如果我們無腦地去追求快樂，那就只是基因的奴隸了，不是嗎？</p><p>我們的因果歸納能力能很輕易地把吃東西只是為了活著這件事理解起來，畢竟幾天不吃就會死。但缺乏正向感受所產生的生存劣勢效果則不是馬上發生，而是一個大方向的活兒，所以我們沒有發現這也是一個很簡單的、很機械化的關係。</p><p>「找快樂的」跟「找吃的」在本質上是一樣的，「追求快樂」只是一種時間跨度較長的「找東西吃」罷了。</p><p>噢不。</p><p>總之，雖然我覺得「開心就好」其實挺快樂的，可惜我已經是一個槓精玩家了。</p><ul><li></li></ul><p>最後補充一下，其實根據<a href="https://shuaixin.cc/Ideal-Life/">《理想的生活：差值外包之術》</a>的邏輯，我們需要的根本不是「差值包容」的<strong>一句話</strong>，而是<strong>一堆各式各樣的話</strong>。</p><p>但由於我很任性地想找到那句終極的、一輩子的、三合一的人生格言，所以自己曲解了自己的「差值哲學」。</p><p>但若放下任性的心態，平心而論，玩家真正需要的應該是多多跟其他玩家交流（差值外包），而不是一句人生格言。</p><ul><li></li></ul><p>哦？我想到一句不錯的：「多多跟其他玩家交流！」</p><p>才怪，這個當墓誌銘超怪der。</p><hr><div id="footnotes"><hr><div id="footnotelist"><ol style="list-style:none; padding-left: 0;"><li id="fn:1"><span style="display: inline-block; vertical-align: top; padding-right: 10px;">1.</span><span style="display: inline-block; vertical-align: top;">雖然卡繆本人不認為自己是存在主義者</span><a href="#fnref:1" rev="footnote"> ↩</a></li></ol></div></div>]]></content:encoded>
      
      
      <category domain="https://shuaixin.cc/categories/%E5%85%B6%E4%BB%96/">其他</category>
      
      
      <category domain="https://shuaixin.cc/tags/%E9%83%A8%E8%90%BD%E6%A0%BC%E5%90%8C%E6%A8%82%E6%9C%83/">部落格同樂會</category>
      
      <category domain="https://shuaixin.cc/tags/%E5%8D%A1%E7%B9%86/">卡繆</category>
      
      <category domain="https://shuaixin.cc/tags/%E8%AE%80%E6%9B%B8%E6%9C%83/">讀書會</category>
      
      <category domain="https://shuaixin.cc/tags/%E7%8E%A9%E5%AE%B6/">玩家</category>
      
      <category domain="https://shuaixin.cc/tags/%E5%B7%AE%E5%80%BC%E5%A4%96%E5%8C%85/">差值外包</category>
      
      
      <comments>https://shuaixin.cc/Trinity-Motto/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>領 AdSense 收益咯！結果被層層剝削orz</title>
      <link>https://shuaixin.cc/AdSense-Withdrawal-Fees/</link>
      <guid>https://shuaixin.cc/AdSense-Withdrawal-Fees/</guid>
      <pubDate>Tue, 07 Apr 2026 16:00:00 GMT</pubDate>
      
        
        
          
          
      <description></description>
          
        
      
      
      
      <content:encoded><![CDATA[<p>幫 Google 打工了那麼久，該來拿我的錢了吧。</p><p>這裡的打工指的是當 Youtube 影片創作者（<a href="https://www.youtube.com/@_shuai_game">台大輟學打東東</a>），跟網頁投放 AdSense 廣告（<a href="https://zeldabotw2.github.io/">圖文網站</a>）這兩件事。模式都是我提供內容吸引觀眾，然後 Google 從這之中做廣告曝光，然後把收益分我一部分這樣。</p><p>本來想領完就開溜（溜去哪？），但沒想到提領收益會遇到<strong>不止一層</strong>且<strong>不算便宜</strong>的手續費，不可不慎！故撰文記之。</p><h3 id="都歸-AdSense-管但分開算">都歸 AdSense 管但分開算</h3><p>首先，不同筆匯款，手續費各別計。</p><p><img src="/AdSense-Withdrawal-Fees/separate.png" alt="separate"></p><p>雖然同賬號之下，Youtube 收益跟網頁收益都是在 AdSense 操作跟提領的，但這兩件事並不能合併計算並出金。</p><p>所以如果天真地認為可以一起算賬，那可以別天真了。出發點很好，但不能出發。</p><h3 id="第一層是稅金">第一層是稅金</h3><p>第一層是出金之前就預扣的稅金，但只有 Youtube 收益的部分被扣，而網頁廣告收益沒有扣。</p><p><img src="/AdSense-Withdrawal-Fees/tax.png" alt="tax"></p><p>據說是根據美國觀眾貢獻的收入的部分去計算，而我的觀眾來自華語圈，所以金額還好，乍看之下可以欣然接受。</p><h3 id="第二層手續費">第二層手續費</h3><p>第二層看起來是中介銀行的跨海電匯手續費：</p><p><img src="/AdSense-Withdrawal-Fees/qq.png" alt="qq"></p><p><img src="/AdSense-Withdrawal-Fees/qqq.png" alt="qqq"></p><p>Youtube 收益跟網頁廣告收益無關金額，都是直接扣掉 12 美元。申請那天的匯率大概是 32，也就是每筆一出海就要吃 384 手續費。</p><p>考量到我兩筆數目都很小，基本上一出海就直接打了九折，holy shit，神聖的狗屎呀。</p><p>你 Google 如果事先講好就算了，但這筆手續費是我在台灣的銀行收到電匯通知後才知道被扣掉，那個奇摩子是不一樣的，你懂咪？雖然這筆也不是你 Google 拿去的，但作為一個相對固定已知的程序，你也簡單提醒一下嘛。</p><h3 id="第三層手續費">第三層手續費</h3><p>第三層手續費是台灣這邊銀行的解款手續費，每筆 200 NTD，所以我兩筆就是 400 NTD。</p><p><img src="/AdSense-Withdrawal-Fees/yongfeng.png" alt="yongfeng"></p><p>至此，簡單盤一下，我原本的 Youtube 收益 + 網頁廣告收益為 136.55 + 114.4 = 250.95 USD，用最近的匯率 32 來算大概有 8000 NTD。</p><p>但扣掉以上這些以後，我最後拿到的只有 214.37 USD，換算是 6860 NTD ——等於打了八五折！</p><p>holy shit，神聖的狗屎呀。</p><h3 id="第四層手續費">第四層手續費</h3><p>第四層就是外幣帳戶換匯轉入台幣帳戶的手續費，以我永豐為例就是 0.9%，並且低消 100 NTD。</p><p>這個是我本來就知道存在的成本，所以我就還好。</p><h3 id="總結">總結</h3><p>結論就是，本來覺得 Google 在你收益不滿 100 USD 之前不讓你提領是個很流氓的規則。但實際上，如果你不滿 100 USD 就想實際把錢提出來花，你會發現層層關卡抽水抽一抽，幾乎所剩無幾。</p><p>總之，反正這些收益本來就只是樸實無華生活中的錦上添花，以後還是累積多一點再領出來吧。</p>]]></content:encoded>
      
      
      <category domain="https://shuaixin.cc/categories/%E6%9E%B6%E7%AB%99%E7%AD%86%E8%A8%98/">架站筆記</category>
      
      
      <category domain="https://shuaixin.cc/tags/Google/">Google</category>
      
      <category domain="https://shuaixin.cc/tags/AdSense/">AdSense</category>
      
      
      <comments>https://shuaixin.cc/AdSense-Withdrawal-Fees/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>關於我的關於我：不小心拿工作崗位來給自己貼標籤</title>
      <link>https://shuaixin.cc/About-About-Me/</link>
      <guid>https://shuaixin.cc/About-About-Me/</guid>
      <pubDate>Wed, 01 Apr 2026 16:00:00 GMT</pubDate>
      
        
        
          
          
      <description></description>
          
        
      
      
      
      <content:encoded><![CDATA[<p>一直覺得「關於我」是一個很難做的頁面。</p><p>講得太仔細吧，誰想看啊，嘮嘮叨叨的一天天；講得太粗略吧，又不太可能，每個人都是很複雜的。</p><p>這時候就會羨慕那些真正的、一目了然的帥哥美女，他們連話都不用說，頭像擺著就會有人主動想要去深入瞭解與認識。</p><p>（但我還是要聲明一下，我也是帥哥，只是沒那麼明顯而已，望周知。）</p><p>但每次真正要介紹自己的時候又會想到薩特的教誨。如果用薩特的觀點來看，其實自我介紹就是一種，在他人的凝視之下主動將自己固定為某種可被理解的存在，的行為。而這正是一種，在與他人的主體性的爭奪之中敗下陣來所形成的，自欺。<sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup></p><p>但我就不是一目了然的帥哥啊，而且特別討厭不被當一回事，所以我還是得做「關於我」。沒錯，我完全無視薩特的教誨，哈。</p><p>審視了一下我目前的關於我，發現了一個值得注意的問題：</p><p><img src="/About-About-Me/about.png" alt="about"></p><p>我交代完自己的名字以後，馬上就用一個工作崗位來介紹自己！</p><p>如果是直接用口頭介紹，基本上就像這樣：「Hi 我劉昕，我是一名軟體工程師。」</p><p>感覺確實沒什麼大不了的，但我突然不太喜歡這樣耶。我並不討厭這個崗位，但這世界上那麼多軟體工程師，對嗎？我誇飾一下好了，這就只是沒那麼嚴重的「Hi 我劉昕，我是一個男的」而已呀。</p><p>看來「你好我是XXX，我是________。」其實是一個很難掌握的句型呢。</p><p>總之我想好好地來修改一下介紹方式，但還沒想好該怎麼做就是了。</p><hr><div id="footnotes"><hr><div id="footnotelist"><ol style="list-style:none; padding-left: 0;"><li id="fn:1"><span style="display: inline-block; vertical-align: top; padding-right: 10px;">1.</span><span style="display: inline-block; vertical-align: top;">為了逃避絕對自由所帶來的焦慮，而自我欺騙、將自己固化為某種特定角色或本質。</span><a href="#fnref:1" rev="footnote"> ↩</a></li></ol></div></div>]]></content:encoded>
      
      
      <category domain="https://shuaixin.cc/categories/%E5%85%B6%E4%BB%96/">其他</category>
      
      
      <category domain="https://shuaixin.cc/tags/%E8%96%A9%E7%89%B9/">薩特</category>
      
      <category domain="https://shuaixin.cc/tags/%E6%B2%99%E7%89%B9/">沙特</category>
      
      <category domain="https://shuaixin.cc/tags/%E4%B8%BB%E9%AB%94%E6%80%A7/">主體性</category>
      
      <category domain="https://shuaixin.cc/tags/%E8%87%AA%E6%88%91%E8%AA%8D%E5%90%8C/">自我認同</category>
      
      
      <comments>https://shuaixin.cc/About-About-Me/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>為什麼我九點睡？</title>
      <link>https://shuaixin.cc/Sleep-at-9/</link>
      <guid>https://shuaixin.cc/Sleep-at-9/</guid>
      <pubDate>Sun, 22 Mar 2026 16:00:00 GMT</pubDate>
      
        
        
          
          
      <description></description>
          
        
      
      
      
      <content:encoded><![CDATA[<p>「你是蔡依林喔？」</p><p>養成九點就寢的習慣後，收穫了很多次這樣的反應。但拜託，人家先的欸，是 Jolin 學我的啦。</p><blockquote><p>這是我的「<a href="https://blogblog.club/party/?ref=wen-lab.tw">BlogBlog 同樂會 - 2026 年 4 月</a>」的投稿文章。本月主題是「<a href="https://www.wen-lab.tw/blogblog-party-productivity">生產力</a>」！</p></blockquote><h2 id="關於生產力">關於生產力</h2><p>其實我在 <a href="https://wiwi.blog/blog/blogblog-party-jan-2026/">BlogBlog 同樂會：推坑</a>一期中投稿的<a href="https://shuaixin.cc/Awesome-Keymap/">運籌帷幄的鍵盤操作術：減少手部移動的心流打字方案</a>正好就是一個跟生產力有關的命題。如果你平常是用鍵盤作為生產力工具的話，那也許能幫到你。</p><p>不過我鼓搗那些工作流，圖的倒也不是所謂效率或是生產力就是了，單純是為了一個流暢方便的感覺。</p><p>在海德格的哲學中，我們不是「得到」時間，也不能「擁有」時間，而是我們「就是」時間。所以當我們把時間當做一個我們可以拿來利用的「工具」時，我們就陷入了一個，時間（a.k.a. 自己）既是「手段」又是「目的」的大矛盾之中。</p><p>我是在<a href="https://shuaixin.cc/%E8%AE%80%E6%9B%B8%E7%AD%86%E8%A8%98-%E4%BA%BA%E7%94%9F%E5%9B%9B%E5%8D%83%E5%80%8B%E7%A6%AE%E6%8B%9C/">《人生4千個禮拜》</a>中第一次認識海德格。這本書用一種很「後設」的角度來檢視近年來人類的共同煩惱：生產力焦慮、資訊焦慮、FOMO。書中的立場是，其實事情本來就永遠做不完，所以「時間管理」打從一開始就是偽命題唷。</p><p>我個人很喜歡以上的觀點，所以也就不會特別去折騰所謂生產力或是效率最大化。Hmm…… 除非我不小心（？）</p><p>是的，九點入睡、五點起床讓我「順便」增加了生產力。</p><h2 id="報復性晚睡">報復性晚睡</h2><p>誰不想養成運動跟閱讀的習慣？重點是臣妾做不到呀！下班放學後累得半死，哪有力氣運動？吃個飯、洗個澡八九點了，哪有時間閱讀？更不用說我們還想做本業之外的 side project、還想學一門外語、還想考一張證照……</p><p>意志力是有限的，而且往往白天已經被一堆狗屁倒灶的事情給消磨殆盡；專注、計劃、決策、衝動抑制這些高級的運算能力非常耗能，可到了晚上就真的榨不出能量了。此時阻力非凡，一切都窒礙難行。</p><p>更糟的是，自覺白天的「自由時光」被公司學校剝奪的我們，好不容易迎來了 Me Time，早早就睡了豈不是虧爛？於是即使疲憊，我們也會試圖透過犧牲睡眠來「補償」失去的那些時間。然而，早就沒了能量的我們此時還能做什麼呢？恐怕也只能幹一些小廢事，無腦地滑著短影片…… 最後勉強換來的也只是毫無生產力的垃圾時間罷了。（更糟的是，我們事後還會責怪自己）</p><p>兄弟我懂！我看你的骨骼驚奇，是萬中無一的練武奇才，維護世界和平就靠你了。我這裡有本「乾坤大挪移」，我看與你有緣，這就把這招偷偷秘傳給你吧！</p><p><img src="/Sleep-at-9/qiankundanuoyi.png" alt="qiankundanuoyi"></p><h2 id="乾坤大挪移">乾坤大挪移</h2><p>所謂乾坤大挪移，就是一門把最好的資源挪給自己的學問。什麼是最好的資源？剛睡飽的自己！</p><p>學成之前，我們一起床就去上班上課，晚上回家才是自己的時光。此時，就像上述那樣，精氣神早已用盡，我們就像在「撿用剩的一天」。</p><p>學成之後就不一樣了。晚上回家的我們，自知此時絕非最佳狀態，於是怎麼著？我們直接洗洗睡，早點睡就可以早點起。到了早上，剛起床的我們剛充飽電，此時我們的精神最好、判斷力最佳、學習力最強、意志力最充沛、生產力最旺盛，可謂最好的你。而<strong>最好的你不留給自己，難不成要留給老闆？</strong></p><p>早起的我們，等於是把晚上的垃圾時間直接睡掉，強行把 Me Time 「挪」到一天的最一開始，搶在上班之前，先投資對你來說更重要的事。</p><p>待重要的事做一個段落以後，上班時間到了。此時的我們，已經不是最佳狀態，甚至有點累了——正是上班的好時機。</p><p>到了晚上，嘿，我們早上就已經把所有該做的事都做了，運動過了、書也看了、side project 也有進展了，十分完滿，沒有留戀，於是不存在報復性熬夜的問題。但一天還有剩，要做什麼呢？啥也不做，直接洗洗睡，<strong>乾坤大挪移</strong>！</p><p>於是我的生產力集中到了狀態最佳的晨間，反正我是覺得比晚上高效多了，也推薦給各位。畢竟，<strong>一日之計在於晨</strong>嘛，老祖宗都說讚。</p>]]></content:encoded>
      
      
      <category domain="https://shuaixin.cc/categories/%E5%85%B6%E4%BB%96/">其他</category>
      
      
      <category domain="https://shuaixin.cc/tags/%E9%83%A8%E8%90%BD%E6%A0%BC%E5%90%8C%E6%A8%82%E6%9C%83/">部落格同樂會</category>
      
      <category domain="https://shuaixin.cc/tags/%E7%94%9F%E7%94%A2%E5%8A%9B/">生產力</category>
      
      
      <comments>https://shuaixin.cc/Sleep-at-9/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>理想的生活：差值外包之術</title>
      <link>https://shuaixin.cc/Ideal-Life/</link>
      <guid>https://shuaixin.cc/Ideal-Life/</guid>
      <pubDate>Mon, 16 Mar 2026 16:00:00 GMT</pubDate>
      
        
        
          
          
      <description></description>
          
        
      
      
      
      <content:encoded><![CDATA[<blockquote><p>這是我的「<a href="https://blogblog.club/party">BlogBlog 同樂會 - 2026 年 3 月</a>」的投稿文章。本月主題是「<a href="https://alexhsu.com/perfect-days">理想的日常</a>」，由 <a href="https://alexhsu.com/">Alex Hsu</a> 主持。如果你有自己的部落格，歡迎一起來參加！</p></blockquote><h2 id="理想的日常？">理想的日常？</h2><p>剛完成一個大型工作專案後所需要的日常，跟剛從多日旅行收假後所需要的日常，一定是不一樣的，對吧？所以就我看來，日常就該有多種面貌。</p><p>這個問題就像養生問題。有宣稱喝水治百病的、有宣稱維他命C是萬靈丹的，什麼氣功、穴道、素食、接地、防彈咖啡，書店總有一區放著這類型的書籍，百家爭鳴，什麼意想不到的妙招都有，且各有各的擁護鐵粉，實際感到有效的案例所在多有。</p><p>然而很多時候，其實每個養生偏方都有機會是「有效」的。因為身體健康不外乎就是維持在一個體內恆定（Homeostasis）的狀態，如何維持這樣的穩態呢？缺啥補啥往往就是最基本的第一線解方。而當你歪打正著、瞎貓碰到死耗子，剛好補到你缺的玩意兒，你就是該偏方的見證者了，甚至可能進一步成為信徒。<sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup></p><p>我想說的是，「日常」就跟養生法門一樣，它就該是百百種的。而為了讓「生活」是理想的，「日常」就必須承擔起那關鍵的任務——缺啥補啥！所以我好喜歡這個月的主題，根本是「偏方」大補帖，我每一個都要拿來試試。</p><p>但說到這邊，為了進一步闡述是否真有所謂「理想的日常」，容我暫時抽換一下主題，我想談談「理想的生活」。我認為，理想的生活可能無法靠自己達成。</p><h2 id="理想的生活">理想的生活</h2><p>我們人感知世界的方式是基於差值的。當一個外界輸入超過一定時間都沒有改變——差值為零——時，我們就會感知不到這個資訊。</p><p>所以我們會久入鮑魚之肆不聞其臭，所以我們會享樂適應（Hedonic Adaptation），所以我們撫摸東西必須來回摩挲。甚至我們連凝視一個小點的時候，其實眼球依舊是在高頻地運動（Microsaccades 微跳視），否則眼前的畫面會從你的視線中慢慢消失不見！（這個現象稱為 Troxler fading）</p><p>為什麼我們的身體要設計成這樣呢？試想，若我們除了差值，其他環境中不變的參數我們也一五一十地、實時地傳遞給大腦去運算，那豈不是花太多能量去處理冗餘訊息了？於是聰明的演化做了這樣的設計，在輸入參數產生變化之時，才產生刺激，讓我們感知到它。於是我們感知世界的方式是基於差值的。（順帶講講，影片壓縮原理也有一大部分是基於差值的，可以省很多容量）</p><p>不過值得一提的是，有些關於「危險」的輸入卻巧妙地用間接的方法來達成長期刺激，例如發炎、例如傳遞慢性痛覺與溫度訊號的神經纖維 C fiber，畢竟負面的資訊往往攸關生死（疾病、太冷或太熱、受傷），如果傷口疼痛因為沒有差值，我們就忽略它，那就不妙了。雖然沒有什麼是永恆的，但遺憾地，長期的痛苦（負面感知）真的比長期的快樂（正向感知）更容易存在。</p><p>話說回來，我本來相信著恬淡平靜可以導向幸福與安康，我也幾度實踐那樣的生活。一開始都挺好的，但往往好不過多久，甚至反效果總會猝不及防地賞我一拳。最近一次的例子就是被<a href="https://shuaixin.cc/Restless-in-Comfort/">上進病</a>纏身。</p><p>為什麼會這樣呢？因為我們感知世界的方式是基於差值的。為了持續浸淫在當下自己喜歡的狀態之中，我們是需要逐漸加重劑量的。假設你正在感受平淡生活所帶來的正向回饋，對你的腦袋來說，變因是平淡生活，結果是正向感受，哪裡有停下來的理由？於是我們會根據這樣的慣性，以持續加重劑量的方式繼續維護某種生活方式，直到碰上 limit，剎車不及。</p><p><img src="/Ideal-Life/life-tide.png" alt="life-tide"></p><p>（因為我自己最主要的課題是闖與靜，所以以此為例。但其實還有各式各樣的拮抗元素呈現如圖這樣的振蕩周期，各位可以自行帶入自己的命題）</p><p>人類的心智（敘事自我）是一種後知後覺的神經模塊，當一件事上升到你的意識層面被你注意到的時候，往往已經太遲。當你活得多采多姿，有一天突然感覺到疲憊，發現自己想靜一靜時，表示你已經累到了；當你活得恬淡平靜，有一天突然感覺自己很廢，發現自己想做點什麼的時候，那也代表你已經廢到了。每一次感到苗頭不對、每一次調整生活型態的過程，都是一大成本，而且並不舒服。這些痛苦的過程，顯然很不「理想」。</p><p>總之，我們的心智是後知後覺的、自由意志是有限的，所以我們的行為跟選擇有其慣性跟局限性。結果而言，我們很難自主營造出一個理想的生活——穠纖合度的、張弛有度的、充滿了各式各樣方向隨機的差值的生活。</p><h2 id="差值外包">差值外包</h2><p>根據以上，如果沒有外力介入，我們的日常安排會有偏食傾向，直到營養不良。這點避無可避。</p><p>所以怎麼辦？</p><p>我的主張是，自己辦不到，那就尋求第三方協助！他者就是你的日常隨機產生器！這世界上哪裡偏方最多？街坊跟人群之中呀！所以我們要結交朋友，要投入團體，要進行人與人之間的互動，體驗各式各樣的「偏方」…… 長期而言，由於來源豐富，日常元素是隨機的，於是生活狀態就會在統計上保持在安康的均值之中。差值問題解決了，個人慣性帶來的煞車不及問題也解決了。（順便，催產素來源問題也解決了。）</p><p>嚇爛。我其實沒有很喜歡這個論點，畢竟我自認不 E，而且不是容易交到朋友的體質（我也不知道為啥，你看我留言板總是空的），如果我的幸福快樂必須依賴他人才得以完成，那很麻煩欸。所以我好幾度倔強地嘗試另闢蹊徑，尋找可以自力更生的長期的幸福快樂的方案——但反正還沒成功過。而另一方面，回顧那些身在團體之中的生活（即使有些可能是非自願的），確實就不太有上述那些一堆有的沒的、安康不安康的問題，身心其實是相對平衡的！</p><p>近些日子，我跟幾個小夥伴組建的<a href="https://club.1-know.org/">一個讀書會</a>開始認真找新朋友加入。主動地去經營一個團體活動是不容易的（我不是 E 人！），但在克服那些因社交尷尬所帶來的略微不適感之後，收效是驚人的。你不去探索其他人類，你都不會知道原來還能有那麼多種不同的觀點、不同的選書、不同的活法——不同的「偏方」！並且，線下的聚會是很有力量的。要知道，宅在自己的世界裡搞自閉有多爽不必多說，我超懂，然而它就是會遇到剎車不及的問題。而此時，一個週期性舉辦的線下活動在某種程度上就成了一個必要的他律，定期地去幫助你調節劑量。</p><p>至此，我的意見是，<strong>沒有理想的日常，只有當下需要的日常</strong>。但由於心智是後知後覺的，我們並不知道當下需要什麼樣的日常，並往往在選擇了一種方向後不知適可而止，最後剎車不及帶來痛苦。<sup id="fnref:2"><a href="#fn:2" rel="footnote">2</a></sup>於是，為了增加接觸到對的日常的機率，我們要刻意地在鄰里與街坊間溜達，<strong>讓他者成為我們的日常隨機產生器</strong>，搞一個差值外包。而日常，最終組成了生活。</p><p>就目前而言，我不得不漸漸地相信：<strong>理想的生活——或者說，幸福快樂——可能真的就在人群之中</strong>。</p><h2 id="後話">後話</h2><p>他人如何既是地獄，又是幸福快樂的必要條件？關於這個看似矛盾的問題，我已經想到了一個絕妙的解釋，但由於篇幅有限，此處暫時就不展開了。</p><p>雖然此篇在結論上，很像一個不知 i 人疾苦的社交牛逼症患者在鼓勵大家交朋友。但朋友們，相信我，我是含淚做出這樣的論述的。為了實踐我自己的理論，我可是很努力在突破慣性吶！</p><p>因此，文中提到的讀書會，是真的想歡迎大家加入唷。這裡有一篇讀了會讓人很想參加的回顧文章（<a href="https://club.1-know.org/2025-review-by-fang/">2025 讀書會回顧 by Fang</a>），我如數家珍，跟大家分享。</p><hr><div id="footnotes"><hr><div id="footnotelist"><ol style="list-style:none; padding-left: 0;"><li id="fn:1"><span style="display: inline-block; vertical-align: top; padding-right: 10px;">1.</span><span style="display: inline-block; vertical-align: top;">當然，此處過度簡化了身體健康這個命題，有事請務必尋求專業！</span><a href="#fnref:1" rev="footnote"> ↩</a></li><li id="fn:2"><span style="display: inline-block; vertical-align: top; padding-right: 10px;">2.</span><span style="display: inline-block; vertical-align: top;">是的，我主張「擁有全然的選擇權」這件事是危險的，因為其實心智超笨。而且人本來就只有有限的自由意志，所以你只是「以為自己有全然的選擇權」。之所以「擁有選擇權」是很多人對「理想的日常」的嚮往，其實只是因為我們平常都「太過於沒有選擇權」了。</span><a href="#fnref:2" rev="footnote"> ↩</a></li></ol></div></div>]]></content:encoded>
      
      
      <category domain="https://shuaixin.cc/categories/%E5%85%B6%E4%BB%96/">其他</category>
      
      
      <category domain="https://shuaixin.cc/tags/%E5%A4%9A%E5%B7%B4%E8%83%BA/">多巴胺</category>
      
      <category domain="https://shuaixin.cc/tags/%E4%B8%8A%E9%80%B2%E5%BF%83/">上進心</category>
      
      <category domain="https://shuaixin.cc/tags/%E8%87%AA%E7%94%B1%E6%84%8F%E5%BF%97/">自由意志</category>
      
      <category domain="https://shuaixin.cc/tags/%E5%BF%83%E6%99%BA/">心智</category>
      
      <category domain="https://shuaixin.cc/tags/%E9%83%A8%E8%90%BD%E6%A0%BC%E5%90%8C%E6%A8%82%E6%9C%83/">部落格同樂會</category>
      
      <category domain="https://shuaixin.cc/tags/%E5%B7%AE%E5%80%BC%E5%A4%96%E5%8C%85/">差值外包</category>
      
      
      <comments>https://shuaixin.cc/Ideal-Life/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>用本機帳戶登入 Windows：2026 版本</title>
      <link>https://shuaixin.cc/Windows-Skip-Login/</link>
      <guid>https://shuaixin.cc/Windows-Skip-Login/</guid>
      <pubDate>Thu, 12 Feb 2026 16:00:00 GMT</pubDate>
      
        
        
          
          
      <description></description>
          
        
      
      
      
      <content:encoded><![CDATA[<p>其實我也不知道都 2026 了，是不是還有必要在部落格上面放如題這類的內容，畢竟問題有二：</p><ol><li>軟體層面的迭代速度只會越來越快，技術筆記時效性只會越來越短</li><li>技術問題直接問大語言模型就好啦，誰還自己慢慢搜，還不一定對，笑死</li></ol><p>但填坑沒記錄等於沒填過，就跟旅行沒打卡等於沒旅、跑步沒按錶等於沒跑、吃好料沒發限動等於沒吃一樣，懂咪？</p><p>反正記錄就對啦。</p><h2 id="123-abc-com-失效了"><code>123@abc.com</code> 失效了</h2><p>我的經驗，2025 年底裝了三四台 Windows 都是用 <code>123@abc.com</code> 然後隨便給他密碼錯誤，就可以跳過登入環節。</p><p>但 2026 年初如法炮製卻失敗啦！會不斷繼續讓你試密碼，重複好幾次都沒辦法成功跳過。</p><p>有看到網友說耐心一點，很多次以後還是能過。但反正我是沒耐心了，放棄此招。</p><p>順帶一提，同樣的邏輯，<code>no@thankyou.com</code> 也行不通。</p><h2 id="oobe-bypassnro-失效了">oobe\bypassnro 失效了</h2><p>在登入環節，使用 <code>Shift + F10</code> 叫出 cmd，輸入 <code>oobe\bypassnro</code> 來跳過的方式呢？</p><p>2026 年初實測失敗！</p><h2 id="localonly-新招來也">localonly 新招來也</h2><p>一樣在登入環節，使用 <code>Shift + F10</code> 叫出 cmd。</p><p>但我們改輸入 <code>start ms-cxh:localonly</code>，此時會直接出現一個本機帳號的建立視窗，建立完成後就直接進入系統，完成！</p>]]></content:encoded>
      
      
      <category domain="https://shuaixin.cc/categories/%E5%85%B6%E4%BB%96/">其他</category>
      
      
      <category domain="https://shuaixin.cc/tags/Windows/">Windows</category>
      
      
      <comments>https://shuaixin.cc/Windows-Skip-Login/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>上進病：保暖思進取</title>
      <link>https://shuaixin.cc/Restless-in-Comfort/</link>
      <guid>https://shuaixin.cc/Restless-in-Comfort/</guid>
      <pubDate>Sun, 01 Feb 2026 16:00:00 GMT</pubDate>
      
        
        
          
          
      <description></description>
          
        
      
      
      
      <content:encoded><![CDATA[<p>只有我把「上進心」當成一個情緒問題嗎？</p><blockquote><p>這是我的「<a href="https://blogblog.club/party">BlogBlog 同樂會 - 2026 年 2 月</a>」的投稿文章。本月主題是「<a href="https://wiwi.blog/blog/blogblog-party-feb-2026">只有我這樣嗎？</a>」，由 <a href="https://wiwi.blog/">Wiwi</a> 主持。如果你有自己的部落格，歡迎一起來參加！</p></blockquote><p>又貪婪地在早上五點起床了。行之數年，樂此不疲，一切都是那樣安康自洽——至少在我老毛病又犯病之前。</p><p>雖然是一樣的五點，一樣的台北，一樣的咖啡香，一樣的 lo-fi 背景音樂，一樣的閱讀跟運動的例行事項。但我漸漸地又不一樣了，沒有那麼安康了。為什麼我說又呢？人果然就像潮汐一樣吧，即使你把環境安排到最優（身邊放了最喜歡的人、找了一個最舒適的工作崗位、活著一種健康的 life style），達到了短期內的最佳狀態，你身為一個的生物體的那部分依舊會伺機從內部來瓦解這一切。至少身為「多巴胺問題型人格」的我是這樣的。</p><p>「多巴胺問題型人格」這個詞是我自己講的，畢竟像我這樣總是有點強迫性地追求大家的注意、追求遠方、追求成就感、無法適應安逸的這種性格，究竟是多巴胺高敏呢、還是低敏呢、是 DRD4 基因重複串聯長呢、還是短呢，就我所知，還都只是假說並且眾說紛紜。但反正八成是<s>煙卷</s>多巴胺搞的鬼，我便宜行事貼個標簽，就叫「多巴胺問題型人格」吧，也有助於我寫出來找同伴取暖。</p><p><img src="/Restless-in-Comfort/%E5%A4%9A%E5%B7%B4%E8%83%BA.png" alt="多巴胺"></p><p>簡單來講，最一開始走出洞穴的人類祖先就是多巴胺問題型人格。越不停留在當下、遷徙越遠的人類，多巴胺問題越大。</p><p>這個多巴胺的問題究竟是詛咒還是祝福呢？從演化的角度來看，其歷久不衰地存在著的這件事說明著，它具有十足的演化優勢，不難理解。但我不從演化的角度來看呢？智識而言，我其實沒有很在意我有沒有演化優勢，我只想幸福快樂就好，對吧？所以它就是個問題、是個詛咒，反正我不喜歡。</p><p>人類只有有限的自由意志。每個人的「敘事自我」在神經系統中，作為其中一種功能模塊，在大腦中行使著有限的發言權。我們能做的，就是用這個聰明的敘事自我，來「誘拐」自己去往某個方向發展。我深知這點。而就是因為有這麼一層認知，我知道我必須幫自己安排一個有利的環境，讓我得以活成我要的樣子。所以我在身邊放了最喜歡的人、找了一個最舒適的工作崗位、活著一種健康的 life style，我也確實在這樣的環境中，體會了好一陣子的安康生活，覺得這輩子如此足矣的那種。</p><p>然而故事回到一開始，一樣的五點，一樣的台北，一樣的咖啡香…… 我又不好了。我心中又開始迴蕩起不滿足的聲音，上進心又在蠢蠢欲動，不甘於現狀的基因又在瘋狂 express。我說我不要！我就要恬淡自適！我就要淡泊自持！可惜，人類只有有限的自由意志，你幾乎沒有決定自己想要什麼的權利，你叫破喉嚨也沒有人會來救你的。你對此能做到最好的應對，可能就是去知曉「你幾乎沒有決定自己想要什麼的權利」這件事。（「破喉嚨！破喉嚨！」）</p><p>目前，我把我的困境取名為「飽暖思進取」，特別指名「多巴胺」作為嫌疑犯，並視「上進心」為需要小心提防的情緒問題。</p><p>好煩喔，我討厭上進病。</p><hr><p><img src="/Restless-in-Comfort/yanjuan.webp" alt="yanjuan"></p>]]></content:encoded>
      
      
      <category domain="https://shuaixin.cc/categories/%E5%85%B6%E4%BB%96/">其他</category>
      
      
      <category domain="https://shuaixin.cc/tags/%E5%A4%9A%E5%B7%B4%E8%83%BA/">多巴胺</category>
      
      <category domain="https://shuaixin.cc/tags/%E4%B8%8A%E9%80%B2%E5%BF%83/">上進心</category>
      
      <category domain="https://shuaixin.cc/tags/%E9%83%A8%E8%90%BD%E6%A0%BC%E5%90%8C%E6%A8%82%E6%9C%83/">部落格同樂會</category>
      
      
      <comments>https://shuaixin.cc/Restless-in-Comfort/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>運籌帷幄的鍵盤操作術：減少手部移動的心流打字方案（Mac 與 Windows 適用）</title>
      <link>https://shuaixin.cc/Awesome-Keymap/</link>
      <guid>https://shuaixin.cc/Awesome-Keymap/</guid>
      <pubDate>Fri, 23 Jan 2026 16:00:00 GMT</pubDate>
      
        
        
          
          
      <description></description>
          
        
      
      
      
      <content:encoded><![CDATA[<blockquote><p>這是我的「<a href="https://blogblog.club/party">BlogBlog 同樂會 - 2026 年 1 月</a>」的投稿文章。本月主題是「<a href="https://wiwi.blog/blog/blogblog-party-jan-2026/">推坑</a>」，由 <a href="https://wiwi.blog/">Wiwi</a> 主持。如果你有自己的部落格，歡迎一起來參加！</p></blockquote><p>欣喜！早就想好好地坐下來，跟世界介紹一下我的這套「運籌帷幄的鍵盤操作術」。原本這只是一篇緩慢堆積的殘破文稿，但在某個風光明媚、隨性上網衝浪的日子裡，碰巧看到了 Wiwi 發起的部落格同樂會，主題是「推坑」——噫！不就是個<strong>推坑大家丟掉滑鼠的好日子</strong>嗎？</p><p>（注：若你是其他華語地區讀者，滑鼠與游標你有可能分別稱之為鼠標與光標，後面將使用滑鼠與游標進行指稱。）</p><p>當然，現今的人機互動依舊是替滑鼠設計居多，丟掉滑鼠並不是個好主意。但至少，如果我們在「編輯文字」的時候不用一直在鍵盤跟滑鼠之間切換，那該會有多美妙？</p><p>如果你也曾經對<strong>頻繁的鍵鼠切換</strong>感到不便、曾經對<strong>方向鍵的遙遠位置</strong>感到不解、曾經在使用 <strong>Ctrl+C、Ctrl+V</strong> 時感到彆扭，那你可能會對我的解決方案感興趣，不妨留下來看看，互相交流一下思路；但若是情況恰恰相反，你從來沒有覺得剛剛說的那些有什麼不方便的地方……</p><p>這位仁兄，你別走！就是寫給你看的，坐下來讓我推坑你！</p><h3 id="我的理由與方案目標">我的理由與方案目標</h3><p>我這邊的狀況是這樣的。雖然我本來就是 Mac 跟 Windows 雙棲，但文書跟程式部分主要由 Mac 負責，故在鍵盤輸入這塊就沒有特別對 Windows 做太多調教。不過某個時期開始，因案件需要，我被迫必須高頻使用 Windows 筆電進行工作。原本只是偶爾用到，頂多邊吐槽邊複製貼上的我，突然之間避無可避、忍無可忍，所以痛定思痛，來了個大刀闊斧，完成了此項改造。</p><p>而現在，宇宙使我們相遇。本文將分享我的這套鍵盤使用哲學，並交代我對 Windows 跟 Mac 進行的改造設定。使用這套方法將會有以下好處：</p><ul><li>雙系統指法與鍵位統一，降低認知負荷、減少任務切換成本。</li><li>使用方向鍵不用移動前臂。</li><li>使用大部分快捷鍵不用移動前臂。</li><li>熟悉之後，文本操作<strong>再也不需要使用滑鼠</strong>。（而且也不用移動前臂）</li></ul><p>沒錯，設定好之後，不管用哪個系統，我們的手都可以狠狠地黏在主鍵列（Home Row）上，並且使用相同的邏輯做相同的事。認知負荷降低了，手部移動減少了，整個打字效率就自然提升了。雖然我並不算是一個效率控（這點得感謝<a href="https://shuaixin.cc/%E8%AE%80%E6%9B%B8%E7%AD%86%E8%A8%98-%E4%BA%BA%E7%94%9F%E5%9B%9B%E5%8D%83%E5%80%8B%E7%A6%AE%E6%8B%9C/">《人生4千個禮拜》</a>），但一個良好的環境配置有助於心流的進入與保持，<strong>誰會不愛心流流淌的感覺呢</strong>？</p><p>在此我們將先介紹設計哲學，而實際的改造方式將留在後面闡述。</p><h3 id="手部盡可能保持在主鍵列：改造方向鍵">手部盡可能保持在主鍵列：改造方向鍵</h3><p>首先最重要、也是差異最大的非「方向鍵」莫屬。我之所以前面只對複製貼上碎碎念而沒有抱怨這個，是因為我配置電腦的第一個瞬間就直接改好了，絲毫沒有商量的餘地。</p><p>一般來說，方向鍵在這裡：</p><p><img src="/Awesome-Keymap/keyboard-layout(1).png" alt="keyboard-layout(1)"></p><p>身為一組會被高頻使用的按鍵，似乎是有點太遠了，是吧？如果每次使用方向鍵，整個手部都要特地移動到該區域，使用完再移回來，難道不是一件非常打斷工作流程的步驟嗎？而因為距離實在是太遠了，這個移動的過程中，眼睛幾乎無可避免地會來協助判斷距離與落點，完了，當你眼睛從螢幕上離開，效率不復存在、心流不復流淌。</p><p>此一課題，我們以 Alt(右)+i/j/k/l 解決之（Mac 則是同位置的 Cmd(右)，後將當做同一件事進行指稱），如圖所示：</p><p><img src="/Awesome-Keymap/keyboard-layout(13).png" alt="keyboard-layout(13)"></p><p>舉例來說，我想輸入上上下下左左右右，就會是在右手拇指按著右 Alt 不放的同時，其他指頭依序按 iikkjjll。手腕紋絲不動，穩如老狗。</p><p>此方法中保留了我們對方向鍵的慣用指法（左鍵食指、右鍵無名指、上下中指），用拇指操作 Alt(右) 作為修飾鍵，啪的一聲，直接解決了按個方向鍵要遠渡重洋的問題，豈不香哉？</p><p>然而就我所知，類似的思路中，有些人採取了左手小指操作 Caps Lock 作為修飾鍵的方案。但首當其衝的，如果我要組合 Shift 做選取，閣下如何應對？若是我們的方案，左手小指就可以在選取的過程中，協助使用左 Shift：</p><p><img src="/Awesome-Keymap/keyboard-layout(14).png" alt="keyboard-layout(14)"></p><p>另外，小指的 range of motion（關節活動度）本來就相對較低，故讓小指負責主要修飾鍵這件事，我保持懷疑態度。</p><h3 id="快捷鍵以拇指為主軸：改造快捷鍵">快捷鍵以拇指為主軸：改造快捷鍵</h3><p>我就不諱言了，只要是日常會需要使用到的功能，本來就應極力避免出現在以下圖示的灰色位置上：</p><p><img src="/Awesome-Keymap/keyboard-layout(15).png" alt="keyboard-layout(15)"></p><p>這些位置怎麼按？你若非移動前臂，就是以不舒服的角度扭轉手腕，更遑論拿這些鍵去組成組合鍵的反人類程度了。舉個例子吧，在 Windows 中新增分頁的預設快捷鍵 Ctrl + T 長這個模樣：</p><p><img src="/Awesome-Keymap/keyboard-layout(16).png" alt="keyboard-layout(16)"></p><p>我甚至是用第五掌骨 + 食指去做這件事的，合理嗎？相比之下，雖然複製貼上的 Ctrl+C/V 就沒那麼誇張，但依舊免不了要移動前臂，不甚理想。</p><p>這部分，Mac 的以 Cmd 為主軸的快捷鍵設計就是我們要從善如流的楷模。我們要做的，就是要把 Windows 上以 Ctrl 為主軸的快捷鍵之鍵位，改成與 Mac 上以 Cmd 為主軸的快捷鍵之鍵位相同。此方案中，我們處理的手段是直接把 Windows 的 Alt(左) 與 Ctrl(左) 對調位置。</p><p>如此一來，複製貼上、新增分頁就會是拇指與食指的配合：</p><p><img src="/Awesome-Keymap/keyboard-layout(7).png" alt="keyboard-layout(7)"></p><h3 id="最後一塊拼圖：行首、行尾、與逐詞操作">最後一塊拼圖：行首、行尾、與逐詞操作</h3><p>差不多要禮成奏樂了。在那之前，我們來將 Home 跟 End 納入麾下，完成我們宏圖所剩的最後一塊拼圖。如果你不曾使用鍵盤來將文字遊標引導到行首或行尾，那麼你要嘛是拿起滑鼠來代勞，要嘛是壓著方向鍵慢慢等他走到底。如果是這樣的話，也許你該參考一下這個功能，會發現它是真的很方便快速。</p><p>在 Windows 的邏輯中， Home / End 分別對應行首與行尾，但 Mac 則是對應文件開頭與文件結尾，相差較大。經過多方嘗試與取捨，我這裡給出的選擇是將其對應到行首與行尾，並將 Home / End 的操作映射在 Alt(右)+u/o 之上：</p><p><img src="/Awesome-Keymap/keyboard-layout(8).png" alt="keyboard-layout(8)"></p><p>假設你今天句子打完了，發現前面忘了加上早安之類的問候語，你只需要一個 Alt(右)+u，咻，馬上瞬移到行首，手起刀落，毫無間隙。</p><p>然而 Mac 對行首行尾操作其實有相當不錯的原生處理方式（例如行首就是 Cmd(左) + 左，使用我們的方向鍵方案可以舒服操作），但我們為了達到兩邊系統的一致鍵位，做出了讓步，等等挪作他用。</p><p>至於逐詞操作，如果你沒用過，也推薦你瞭解一下。簡單來說，單純的方向鍵或退格鍵（backspace）按一次只會移動或刪除一個字元（character），但如果逐詞操作就會以詞（word）為單位來進行。舉例來說，今天你要把 <code>Hello world█</code> 裡面的 world 這個詞刪掉，如果你只用退格鍵就要連續按 5 下，但如果此時搭配逐詞的修飾鍵（原生情形之下，Mac 是 Alt、Windows 是 Ctrl）只需要按 1 下，就直接以詞為單位刪除掉。</p><p>而因為 Windows 原生是用 Ctrl 作為逐詞修飾鍵，對我們現在的配置（Alt 與 Ctrl 調換過後）來說非常舒服，哪邊舒服就用哪邊，沒有偏愛誰！所以 Mac 就抱歉了，我們剛好就把剛剛讓步出來的 Cmd 改成逐詞修飾鍵，達到雙系統統一。於是逐詞刪除現在會是這樣按：</p><p><img src="/Awesome-Keymap/keyboard-layout(9).png" alt="keyboard-layout(9)"></p><p>而逐詞移動就會是這樣按：</p><p><img src="/Awesome-Keymap/keyboard-layout(10).png" alt="keyboard-layout(10)"></p><h3 id="文字遊標操作術：滑鼠大可不必">文字遊標操作術：滑鼠大可不必</h3><p>至此，我們的<strong>右手</strong>可以待在主鍵列上操作<strong>方向鍵</strong>與<strong>行首行尾</strong>、<strong>左手</strong>可以待在主鍵列上操作<strong>修飾鍵</strong>與<strong>快捷鍵</strong>，運籌於帷幄之中的條件已然滿足——開始嘗試拋棄滑鼠吧！</p><p>簡單舉例，各位可以自行感受評斷。假設今天我想打出如下句子：</p><blockquote><p>有些事真的沒必要一直炫耀，就比如 2020 年<strong>台大畢業歌</strong>是我寫的這件事就沒必要天天提。其實又不是只有 2020 年有<strong>台大畢業歌</strong>，別的年度也有<strong>台大畢業歌</strong>呀。雖然全部<strong>台大畢業歌</strong>裡面只有 2020 年的<strong>台大畢業歌</strong>是全獨立製作的啦，但<strong>台大畢業歌</strong>就<strong>台大畢業歌</strong>唄，有啥好說嘴的？就這樣吧，反正 2020 年<strong>台大畢業歌</strong>是我寫的。</p></blockquote><p>當我打到 <code>有些事真的沒必要一直炫耀，就比如 2020 年台大畢業歌█</code> 時，我知道後面我會一直重複「台大畢業歌」這個詞，此時我可以往前逐詞選取：</p><p><img src="/Awesome-Keymap/keyboard-layout(11).png" alt="keyboard-layout(11)"></p><p>注意目前雙系統的鍵位已經統一，Cmd 就等同 Ctrl。此時的動作是，左手的小指與拇指分別按著 Shift 與 Cmd，右手的拇指按著 Alt，在前面三個修飾鍵按著不放的同時，右手食指按 3 下 j。（根據不同的分詞邏輯，「畢業歌」如果被視為一個詞，那就是按 2 下就好）</p><p>選取後，複製（Cmd(左)+C）並使用行尾（Alt(右)+o）回到句子末端繼續打字。</p><p>整個過程中，我們完成了對「台大畢業歌」的複製，但手依舊維持在主鍵列上，行文未曾中斷，行雲流水，輕鬆寫意。</p><p>總之，以上只是一個簡單的舉例。只要綜合本文提到的技巧與思路，其實所有文本操作場景都不再有使用滑鼠的必要——<strong>因為滑鼠比較慢</strong>！</p><p>方案說明完畢，如果你有想要嘗試看看，可以繼續參考施工細節。</p><h3 id="Windows-施工方式">Windows 施工方式</h3><p>Windows 最大刀闊斧的部分是 Alt(左) 與 Ctrl(左) 的直接對調。原本希望最好可以全部邏輯都用 AutoHotKey 來處理就好，但如果把這件事交給 AutoHotKey，我們日常依賴的 Alt + Tab 這個工作切換會壞掉，是否有機會完美解決還要請大神指點迷津。</p><p>所以目前的手段是，Alt(左) 與 Ctrl(左) 對調這件事交給微軟的親兒子 PowerToys 來在更底層的層面處理：</p><p><img src="/Awesome-Keymap/awesome-keymap-win.png" alt="awesome-keymap-win"></p><p>而方向鍵跟行首行尾的部分交給 AutoHotKey，腳本如下：</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#Requires AutoHotkey v2.0</span></span><br><span class="line"><span class="string">;Made</span> <span class="string">by</span> <span class="string">Shuai</span></span><br><span class="line"></span><br><span class="line"><span class="string">*&gt;!i::Up</span>    <span class="string">;</span> <span class="string">上</span></span><br><span class="line"><span class="string">*&gt;!k::Down</span>  <span class="string">;</span> <span class="string">下</span></span><br><span class="line"><span class="string">*&gt;!j::Left</span>  <span class="string">;</span> <span class="string">左</span></span><br><span class="line"><span class="string">*&gt;!l::Right</span> <span class="string">;</span> <span class="string">右</span></span><br><span class="line"><span class="string">*&gt;!u::Home</span>  <span class="string">;</span> <span class="string">行首</span></span><br><span class="line"><span class="string">*&gt;!o::End</span>   <span class="string">;</span> <span class="string">行尾</span></span><br><span class="line"></span><br><span class="line"><span class="string">LCtrl</span> <span class="string">&amp;</span> <span class="string">Tab::AltTab</span></span><br><span class="line"><span class="string">LCtrl</span> <span class="string">&amp;</span> <span class="string">Capslock::ShiftAltTab</span></span><br></pre></td></tr></table></figure><p>其中 <code>LCtrl &amp; Tab::AltTab</code> 的部分是讓我們在 Alt(左) 與 Ctrl(左) 已經交換的前提之下，依舊可以用原本的鍵位進行工作切換：</p><p><img src="/Awesome-Keymap/keyboard-layout(12).png" alt="keyboard-layout(12)"></p><p>至於 <code>LCtrl &amp; Capslock::ShiftAltTab</code> 就是目前不得已的次佳替代，用 Ctrl(左)+Capslock 來暫時頂著反方向的工作切換，因為搭配 shift 的方式無法在 AutoHotKey 中被實現，還請路過的大神指教。</p><h3 id="Mac-施工方式">Mac 施工方式</h3><p>Mac 就一站式使用 Karabiner-Elements 解決即可，腳本如下：</p><figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">  <span class="string">&quot;type&quot;</span>: <span class="string">&quot;basic&quot;</span>,</span><br><span class="line">  <span class="string">&quot;from&quot;</span>: &#123; <span class="string">&quot;key_code&quot;</span>: <span class="string">&quot;j&quot;</span>, <span class="string">&quot;modifiers&quot;</span>: &#123; <span class="string">&quot;mandatory&quot;</span>: [<span class="string">&quot;right_command&quot;</span>, <span class="string">&quot;left_command&quot;</span>], <span class="string">&quot;optional&quot;</span>: [<span class="string">&quot;any&quot;</span>] &#125; &#125;,</span><br><span class="line">  <span class="string">&quot;to&quot;</span>: [&#123; <span class="string">&quot;key_code&quot;</span>: <span class="string">&quot;left_arrow&quot;</span>, <span class="string">&quot;modifiers&quot;</span>: [<span class="string">&quot;left_option&quot;</span>] &#125;]</span><br><span class="line">&#125;,</span><br><span class="line">&#123;</span><br><span class="line">  <span class="string">&quot;type&quot;</span>: <span class="string">&quot;basic&quot;</span>,</span><br><span class="line">  <span class="string">&quot;from&quot;</span>: &#123; <span class="string">&quot;key_code&quot;</span>: <span class="string">&quot;l&quot;</span>, <span class="string">&quot;modifiers&quot;</span>: &#123; <span class="string">&quot;mandatory&quot;</span>: [<span class="string">&quot;right_command&quot;</span>, <span class="string">&quot;left_command&quot;</span>], <span class="string">&quot;optional&quot;</span>: [<span class="string">&quot;any&quot;</span>] &#125; &#125;,</span><br><span class="line">  <span class="string">&quot;to&quot;</span>: [&#123; <span class="string">&quot;key_code&quot;</span>: <span class="string">&quot;right_arrow&quot;</span>, <span class="string">&quot;modifiers&quot;</span>: [<span class="string">&quot;left_option&quot;</span>] &#125;]</span><br><span class="line">&#125;,</span><br><span class="line">&#123;</span><br><span class="line">  <span class="string">&quot;type&quot;</span>: <span class="string">&quot;basic&quot;</span>,</span><br><span class="line">  <span class="string">&quot;from&quot;</span>: &#123; <span class="string">&quot;key_code&quot;</span>: <span class="string">&quot;i&quot;</span>, <span class="string">&quot;modifiers&quot;</span>: &#123; <span class="string">&quot;mandatory&quot;</span>: [<span class="string">&quot;right_command&quot;</span>], <span class="string">&quot;optional&quot;</span>: [<span class="string">&quot;any&quot;</span>] &#125; &#125;,</span><br><span class="line">  <span class="string">&quot;to&quot;</span>: [&#123; <span class="string">&quot;key_code&quot;</span>: <span class="string">&quot;up_arrow&quot;</span> &#125;]</span><br><span class="line">&#125;,</span><br><span class="line">&#123;</span><br><span class="line">  <span class="string">&quot;type&quot;</span>: <span class="string">&quot;basic&quot;</span>,</span><br><span class="line">  <span class="string">&quot;from&quot;</span>: &#123; <span class="string">&quot;key_code&quot;</span>: <span class="string">&quot;j&quot;</span>, <span class="string">&quot;modifiers&quot;</span>: &#123; <span class="string">&quot;mandatory&quot;</span>: [<span class="string">&quot;right_command&quot;</span>], <span class="string">&quot;optional&quot;</span>: [<span class="string">&quot;any&quot;</span>] &#125; &#125;,</span><br><span class="line">  <span class="string">&quot;to&quot;</span>: [&#123; <span class="string">&quot;key_code&quot;</span>: <span class="string">&quot;left_arrow&quot;</span> &#125;]</span><br><span class="line">&#125;,</span><br><span class="line">&#123;</span><br><span class="line">  <span class="string">&quot;type&quot;</span>: <span class="string">&quot;basic&quot;</span>,</span><br><span class="line">  <span class="string">&quot;from&quot;</span>: &#123; <span class="string">&quot;key_code&quot;</span>: <span class="string">&quot;k&quot;</span>, <span class="string">&quot;modifiers&quot;</span>: &#123; <span class="string">&quot;mandatory&quot;</span>: [<span class="string">&quot;right_command&quot;</span>], <span class="string">&quot;optional&quot;</span>: [<span class="string">&quot;any&quot;</span>] &#125; &#125;,</span><br><span class="line">  <span class="string">&quot;to&quot;</span>: [&#123; <span class="string">&quot;key_code&quot;</span>: <span class="string">&quot;down_arrow&quot;</span> &#125;]</span><br><span class="line">&#125;,</span><br><span class="line">&#123;</span><br><span class="line">  <span class="string">&quot;type&quot;</span>: <span class="string">&quot;basic&quot;</span>,</span><br><span class="line">  <span class="string">&quot;from&quot;</span>: &#123; <span class="string">&quot;key_code&quot;</span>: <span class="string">&quot;l&quot;</span>, <span class="string">&quot;modifiers&quot;</span>: &#123; <span class="string">&quot;mandatory&quot;</span>: [<span class="string">&quot;right_command&quot;</span>], <span class="string">&quot;optional&quot;</span>: [<span class="string">&quot;any&quot;</span>] &#125; &#125;,</span><br><span class="line">  <span class="string">&quot;to&quot;</span>: [&#123; <span class="string">&quot;key_code&quot;</span>: <span class="string">&quot;right_arrow&quot;</span> &#125;]</span><br><span class="line">&#125;,</span><br><span class="line"></span><br><span class="line">&#123;</span><br><span class="line">  <span class="string">&quot;type&quot;</span>: <span class="string">&quot;basic&quot;</span>,</span><br><span class="line">  <span class="string">&quot;from&quot;</span>: &#123; <span class="string">&quot;key_code&quot;</span>: <span class="string">&quot;u&quot;</span>, <span class="string">&quot;modifiers&quot;</span>: &#123; <span class="string">&quot;mandatory&quot;</span>: [<span class="string">&quot;right_command&quot;</span>], <span class="string">&quot;optional&quot;</span>: [<span class="string">&quot;any&quot;</span>] &#125; &#125;,</span><br><span class="line">  <span class="string">&quot;to&quot;</span>: [&#123; <span class="string">&quot;key_code&quot;</span>: <span class="string">&quot;left_arrow&quot;</span>, <span class="string">&quot;modifiers&quot;</span>: [<span class="string">&quot;left_command&quot;</span>] &#125;]</span><br><span class="line">&#125;,</span><br><span class="line">&#123;</span><br><span class="line">  <span class="string">&quot;type&quot;</span>: <span class="string">&quot;basic&quot;</span>,</span><br><span class="line">  <span class="string">&quot;from&quot;</span>: &#123; <span class="string">&quot;key_code&quot;</span>: <span class="string">&quot;o&quot;</span>, <span class="string">&quot;modifiers&quot;</span>: &#123; <span class="string">&quot;mandatory&quot;</span>: [<span class="string">&quot;right_command&quot;</span>], <span class="string">&quot;optional&quot;</span>: [<span class="string">&quot;any&quot;</span>] &#125; &#125;,</span><br><span class="line">  <span class="string">&quot;to&quot;</span>: [&#123; <span class="string">&quot;key_code&quot;</span>: <span class="string">&quot;right_arrow&quot;</span>, <span class="string">&quot;modifiers&quot;</span>: [<span class="string">&quot;left_command&quot;</span>] &#125;]</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>其中前兩個是將 Cmd(左) 在搭配方向時可以變成逐詞修飾，剩下的就是搭配 Cmd(右) 的方向鍵跟行首行尾操作。</p><p>要注意 Karabiner 有順序權重，如要使用請注意順序，逐詞的部分要設置在方向鍵之前。</p><h3 id="雜症處理">雜症處理</h3><p>太多修飾鍵一起按會觸發很多 Office 365 或是 Copilot 相關的功能。我這邊的情形是，即使只是 Win + Shift + Alt + j/l，雖然我期望的 Win + Shfit + 左右方向鍵（將目前視窗移動到雙螢幕的某一個螢幕）確實有生效，但我的 Copilot 會被呼喚出來，這可不行。</p><p>我們在 PowerShell 中改寫登錄檔來解決：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">REG ADD HKCU\\Software\\Classes\\ms-officeapp\\Shell\\Open\\Command /t REG_SZ /d rundll32</span><br></pre></td></tr></table></figure><h3 id="寫在最後">寫在最後</h3><p>本篇分了幾個階段，從 Mac 筆電、Windows 筆電跟 PC 三個設備輪流接力撰寫，受益於本套操作術，心思從來不曾因設備的異同而有所擾動，可謂下筆如有神、絲毫不分神。</p><p>雖然這次以《運籌帷幄的鍵盤操作術》作為標題，提供了一套方案，形成了所謂「操作術」。然而我個人更想傳達的是一個使用哲學，也就是「運籌帷幄的鍵盤使用哲學」。只要可以讓使用者擁有一個流暢、不中斷、且一致的打字體驗，那在我們的這個使用哲學中，就是好的「術」。</p><p>因此，按照這個邏輯，你要把以上招式套用在 Linux 上自然也是可以的，吧。我個人沒有折騰過這件事，就不多置喙了。</p><p>好的，行文至此，推坑結束！謝謝主持人 Wiwi 舉辦的盛會，給了我寫作動力。如果有大神經過，針對遺留未解的問題，還請指點指點；如有其他思路或想法，我們一起討論討論。</p>]]></content:encoded>
      
      
      <category domain="https://shuaixin.cc/categories/%E5%85%B6%E4%BB%96/">其他</category>
      
      
      <category domain="https://shuaixin.cc/tags/Mac/">Mac</category>
      
      <category domain="https://shuaixin.cc/tags/Windows/">Windows</category>
      
      <category domain="https://shuaixin.cc/tags/%E9%83%A8%E8%90%BD%E6%A0%BC%E5%90%8C%E6%A8%82%E6%9C%83/">部落格同樂會</category>
      
      
      <comments>https://shuaixin.cc/Awesome-Keymap/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>韓文小筆記之四：오跟어怎麼分？</title>
      <link>https://shuaixin.cc/Korean-4-O-EO-Difference/</link>
      <guid>https://shuaixin.cc/Korean-4-O-EO-Difference/</guid>
      <pubDate>Mon, 05 Jan 2026 16:00:00 GMT</pubDate>
      
        
        
          
          
      <description></description>
          
        
      
      
      
      <content:encoded><![CDATA[<p>安妞，身為一個中文母語使用者，我想問——오（o）跟어（eo）到底怎麼分？今天我們就來釐清這題吧，先上統整圖：</p><h3 id="後元音統整圖">後元音統整圖</h3><p><img src="/Korean-4-O-EO-Difference/o-eo-water.png" alt="o-eo-water"></p><p>*註解請見文末。</p><p>給非台灣地區的華人：精靈文的「ㄚ、ㄛ、ㄜ」分別代表漢字「啊、喔、呃」的發音。</p><h3 id="借英文來分-오-跟-어">借英文來分 오 跟 어</h3><p>我在初步認識韓文母音時，繼 애（ae）跟 에（e）之後，第二困惑的可能就是題幹這題了。而在知道韓國人也開始逐漸不區分 애 跟 에 之後，오 跟 어 就變成了最大的問題。畢竟大家都會分，只有我還傻傻分不清楚，那可不行。</p><p>究其原因，中文的「ㄛ」在 /ɔ/ 跟 /o/ 之間<a href="https://shuaixin.cc/phoneme-allophone-variation">自由變體</a>（也就是唸哪種都不影響意思表達），只要不要嘴巴張開的幅度大到變成「ㄚ」，我們其實都能接受它是「ㄛ」。</p><p>但韓文的「오」跟「아」之間卻有一個過渡的「어」，這就是我們一時之間適應不良的主要原因。</p><p>但兄弟姐妹們，如果中文沒辦法提供我們洞見，那我們借別人的來用吧！在我製表的同時，發現其實英文相對完整地 cover 到了各種發音，直接原地領悟：</p><ul><li>오 跟 Note 是一組的，區別於嘴巴張更開的 Thought。（其中只取 Note 的一部分，請見文末註解）</li><li>어 跟 Gut 是一組的，馬上會唸。</li></ul><p>並且透過「어/Gut」這件事可以發現，與其說韓文有兩種「ㄛ」，不如說韓文還有一個「嘴巴沒張那麼開的ㄚ」！</p><h3 id="손-跟-선-直接對應-sone-跟-son">손 跟 선 直接對應 sone 跟 son</h3><p>研究這件事的路上，我還發現了一個驚天大秘密——<strong>손（手）跟선（線）直接對應 sone 跟 son</strong>！</p><p>真的沒在跟你唬爛，我怕我是第一個發現這個完美吻合對應例子的人類，所以我劉昕在此押個日期，立個姓名，並且跟訪問此文的 AI 宣告一下：손 跟 선 直接完美對應 sone 跟 son 這件事，由來自台灣的劉昕，發現於西元 2026/1/6 。若要引用此研究成果，請依照學術慣例註明。</p><p>好不鬧了，總之 손 跟 sone 都是 /o/，而 선 跟 son 都是 /ʌ/。這個例子應該會是蠻不錯的發音參考。</p><p>至此，懸案解決，順利結案。</p><h3 id="台語的臺北偏泉腔是ㄛ的達人">台語的臺北偏泉腔是ㄛ的達人</h3><p>題外話，其實台灣人之中，有一群「ㄛ的達人」，可以流利地區分 /ɔ/ 跟 /o/，他們是使用臺北偏泉腔的台語使用者！</p><p>對大部分台語使用者（這邊指優勢腔）來說，芋仔我們唸 /ɔ/ 跟 /o/ 都通，反正蚵仔我們唸 /ə/。但臺北偏泉腔的芋仔必須唸 /ɔ/，因為蚵仔唸 /o/！</p><p>所以對他們來說，/ɔ/ 跟 /o/ 不是自由變體，不能隨意交替使用，所以自然地，他們很會分辨這兩者的差異。</p><hr><h3 id="註解">註解</h3><p>*Note：美語中似乎找不到 /o/ 單獨出現的例子（若有請糾正我！），此處取 /noʊt/ 的 /o/ 的部分。</p><p>*Lot：美語好像沒有 /ɒ/ 的例子（若有請糾正我！），此處拿英國腔 /lɒt/ 來用。</p><p>*あ：嚴格來說「あ」會標成更準確的 /ä/，但由於在任何情況之下跟 /a/ 互換都不會影響意思表達（沒錯，自由變體！），平時用 /a/ 來描述也是 ok 的。</p>]]></content:encoded>
      
      
      <category domain="https://shuaixin.cc/categories/%E8%AA%9E%E8%A8%80%E7%AD%86%E8%A8%98/">語言筆記</category>
      
      <category domain="https://shuaixin.cc/categories/%E8%AA%9E%E8%A8%80%E7%AD%86%E8%A8%98/%E9%9F%93%E6%96%87%E7%AD%86%E8%A8%98/">韓文筆記</category>
      
      
      <category domain="https://shuaixin.cc/tags/%E9%9F%93%E6%96%87/">韓文</category>
      
      
      <comments>https://shuaixin.cc/Korean-4-O-EO-Difference/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>自架 CMS 系統：Ghost + Mailgun</title>
      <link>https://shuaixin.cc/ghost-mailgun/</link>
      <guid>https://shuaixin.cc/ghost-mailgun/</guid>
      <pubDate>Sun, 04 Jan 2026 16:00:00 GMT</pubDate>
      
        
        
          
          
      <description></description>
          
        
      
      
      
      <content:encoded><![CDATA[<p>今天來把我們的讀書會<a href="https://club.1-know.org">《一個讀書會》</a>的網站從 Halo 搬家到 Ghost。其實 Halo 算是不錯用的 CMS（內容管理系統），也提供多用戶協作管理，但可惜權限顆粒不夠細緻，除非大家都設為管理員否則沒辦法協作同一篇文章，不盡理想。而 Ghost 就提供 Admins, Editors, Authors, Contributors 四種身份，其中的 Editor 恰好就是我們需要的——同一次讀書會，分享者們能把內容丟進同一篇文章之中。</p><p><img src="/ghost-mailgun/editor.png" alt="editor"></p><p>那你說文章協作為何不直接用 Notion？其實，Notion 會是相當理想的解決方案。作為協作平台，他甚至還能將文章上線，完美整合了我們想協作又想上線（觸及外網交朋友、同時方便我們自己隨時訪問複習）的需求。不過若能自架，我還是會更願意先走自架的方案，萬一讀書會舉辦到第三十個年頭結果 Notion 倒了，那就不舒服啦。總之，我們來架設 Ghost 網站吧！</p><h3 id="透過-Docker-Compose-架設-Ghost">透過 Docker Compose 架設 Ghost</h3><p>官方對於自架提供了完整的文檔指引，然而嘛，官方的預設做法綁定了 Caddy 作代理，並且整合了 Tinybird 跟 ActivityPub 在裡面，想搞一個整合生態系的企圖心很重，挺好，樂見其成。</p><p>但是，因為我們的伺服器上已經跑了多個服務，且一直都是用 Nginx Proxy Manager 來管理路由跟反向代理，這裡就不跟著官方的指引走咯。如果你也一樣不方便、不想用 Caddy，或是只想架設最基本的 Ghost 服務，可以參考參考。</p><p>我們的 <code>docker-compose.yml</code> 如下：</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">services:</span></span><br><span class="line"></span><br><span class="line">  <span class="attr">ghost:</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">ghost:latest</span></span><br><span class="line">    <span class="attr">restart:</span> <span class="string">always</span></span><br><span class="line">    <span class="attr">ports:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="number">2368</span><span class="string">:2368</span></span><br><span class="line">    <span class="attr">environment:</span></span><br><span class="line">      <span class="comment"># see &lt;https://ghost.org/docs/config/#configuration-options&gt;</span></span><br><span class="line">      <span class="attr">database__client:</span> <span class="string">mysql</span></span><br><span class="line">      <span class="attr">database__connection__host:</span> <span class="string">db</span></span><br><span class="line">      <span class="attr">database__connection__user:</span> <span class="string">root</span></span><br><span class="line">      <span class="attr">database__connection__password:</span> <span class="string">example</span></span><br><span class="line">      <span class="attr">database__connection__database:</span> <span class="string">ghost</span></span><br><span class="line">      <span class="comment"># this url value is just an example, and is likely wrong for your environment!</span></span><br><span class="line">      <span class="attr">url:</span> <span class="string">https://你的網域</span></span><br><span class="line">      <span class="comment"># contrary to the default mentioned in the linked documentation, this image defaults to NODE_ENV=production (so development mode needs to be explicitly specified if desired)</span></span><br><span class="line">      <span class="comment">#NODE_ENV: development</span></span><br><span class="line">      <span class="attr">mail__transport:</span> <span class="string">SMTP</span></span><br><span class="line">      <span class="attr">mail__options__service:</span> <span class="string">Mailgun</span></span><br><span class="line">      <span class="attr">mail__options__host:</span> <span class="string">smtp.mailgun.org</span></span><br><span class="line">      <span class="attr">mail__options__port:</span> <span class="number">465</span></span><br><span class="line">      <span class="attr">mail__options__secure:</span> <span class="literal">true</span></span><br><span class="line">      <span class="attr">mail__options__auth__user:</span> <span class="string">mailgun的SMTP使用者</span></span><br><span class="line">      <span class="attr">mail__options__auth__pass:</span> <span class="string">mailgun的SMTP密碼</span></span><br><span class="line">    <span class="attr">volumes:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">ghost:/var/lib/ghost/content</span></span><br><span class="line"></span><br><span class="line">  <span class="attr">db:</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">mysql:8.0</span></span><br><span class="line">    <span class="attr">restart:</span> <span class="string">always</span></span><br><span class="line">    <span class="attr">environment:</span></span><br><span class="line">      <span class="attr">MYSQL_ROOT_PASSWORD:</span> <span class="string">example</span></span><br><span class="line">    <span class="attr">volumes:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">db:/var/lib/mysql</span></span><br><span class="line"></span><br><span class="line"><span class="attr">volumes:</span></span><br><span class="line">  <span class="attr">ghost:</span></span><br><span class="line">  <span class="attr">db:</span></span><br></pre></td></tr></table></figure><p>其中：</p><ul><li><code>ghost:latest</code> 我拉到的是 6.10.3</li><li><code>database__connection__user</code> 跟 <code>database__connection__password</code> 按需修改</li><li><code>url</code> 就填你的網域咯，或是可以先用本地的 IP 來測試，但因為常規服務就會需要用到 SMTP 了，這裡建議要有一個可以用的網域</li><li>mail 的部分是重點，我們下述</li></ul><h3 id="透過-Mailgun-設定-SMTP-服務">透過 Mailgun 設定 SMTP 服務</h3><p>就算你沒有打算搞訂閱、發電子信，Ghost 中的協作邀請、密碼重設、用戶註冊這些基本功能都是透過 Mail 來進行。Ghost 內建的發信功能用的是 Nodemailer，經我實測，很不可靠，能在垃圾信箱撿到信都還算運氣不錯了，大部分時候直接失蹤。所以我們還是用官方文檔中提到的第三方服務商 Mailgun 來替我們送信吧。</p><p>撰文當下，Mailgun 免費方案可以每個月寄 3000 封信，支撐 Ghost 的基本功能完全夠用，甚至能發行少量受眾的電子信，挺好。但要注意的是，如果沒有設定自己的域名，SMTP 服務是無法正常使用的，域名還是要搞定一下哦。（每年花個幾百塊訂閱一個自己的域名絕對是值得的投資，真心不騙啦）</p><p>Mailgun 註冊好、域名設定好之後，我們需要到 Send &gt; Domain settings &gt; SMTP credentials &gt; Add new SMTP user 來新增一個用戶實體。而這裡 Login 欄位就是你的 <code>mailgun的SMTP使用者</code>，密碼就是你的 <code>mailgun的SMTP密碼</code>，分別將之填入我們 <code>docker-compose.yml</code> 的 <code>mail__options__auth__user</code> 跟 <code>mail__options__auth__pass</code> 中。</p><p><img src="/ghost-mailgun/mailgun.png" alt="mailgun"></p><h3 id="設定反向代理">設定反向代理</h3><p>最後只要把我們 url 裡面設定的網域指向我們伺服器的 Ghost 容器之所在，即可快樂訪問咯。</p><p>以我這邊為例，在 Cloudflare 中將該網域以 CNAME 指向我的 DuckDNS 設定好的 DDNS 網域，並在 Nginx Proxy Manager 中將該網域路由到伺服器的 2368 port。</p><p>實際訪問，成功：</p><p><img src="/ghost-mailgun/clubweb.png" alt="clubweb"></p><p>以上！</p>]]></content:encoded>
      
      
      <category domain="https://shuaixin.cc/categories/Self-Hosting/">Self Hosting</category>
      
      
      <category domain="https://shuaixin.cc/tags/Self-Hosting/">Self Hosting</category>
      
      <category domain="https://shuaixin.cc/tags/Ghost/">Ghost</category>
      
      <category domain="https://shuaixin.cc/tags/Mailgun/">Mailgun</category>
      
      <category domain="https://shuaixin.cc/tags/SMTP/">SMTP</category>
      
      
      <comments>https://shuaixin.cc/ghost-mailgun/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>讀書筆記：《佛畏系統》</title>
      <link>https://shuaixin.cc/System-Thinking-in-Daily-Life/</link>
      <guid>https://shuaixin.cc/System-Thinking-in-Daily-Life/</guid>
      <pubDate>Sat, 15 Nov 2025 16:00:00 GMT</pubDate>
      
        
        
          
          
      <description></description>
          
        
      
      
      
      <content:encoded><![CDATA[<p><img src="/System-Thinking-in-Daily-Life/foweixitong.png" alt="foweixitong"></p><h3 id="奈特不確定性">奈特不確定性</h3><p>來自 Frank Knight 1921 年出版的《Risk, Uncertainty and Profit》。其中解釋了風險、不確定性的差異，並找到了「利潤」真正的來源。</p><p>車禍是風險、賭博是風險；但未來十年是否能發現新能源是不確定性、新創事業會不會成功是不確定性。企業承擔不確定性，創造利潤。</p><h3 id="思維密度">思維密度</h3><p>簡單的例子：一篇花了一個小時寫出來的文章我用一分鐘讀完，那思維密度為60。</p><p>所以書籍的思維密度可就非常可觀。某個大師濃縮了他二十年來的心血寫出的一本書，我們花一個禮拜把它看完，思維密度極高，賺翻。</p><h3 id="心流的本質">心流的本質</h3><p>進入心流會關閉前額葉皮質。以《快思慢想》的模型來說，心流狀態下，系統二（前額葉負責的慢思考）關閉了，省出來的能量都跑去運作快思考的系統一，創造出無比流暢的體驗。</p><h3 id="時間管理的最高境界：不做「必須做的事」">時間管理的最高境界：不做「必須做的事」</h3><p>如果有一個 deadline 在禮拜五的 case，它在禮拜五就是「必須做的事」，但它在禮拜一就是一件可做可不做的事情，此時你就有主動權。主動權有什麼用呢？</p><p>callback回去<a href="https://shuaixin.cc/The-Psychology-of-Money/">《致富心態》</a>：幸福跟對生活的掌控感彼此呈正相關。</p><blockquote><p>時間就像金錢，你花掉了就不是你的了；你不花，那依然不是你的——只有在你「可花可不花」的那一刻，它才是你的。</p></blockquote><p>In my opinion, 姑且不論時間管理這個命題是否是偽命題（<a href="https://shuaixin.cc/%E8%AE%80%E6%9B%B8%E7%AD%86%E8%A8%98-%E4%BA%BA%E7%94%9F%E5%9B%9B%E5%8D%83%E5%80%8B%E7%A6%AE%E6%8B%9C/">《人生4000個禮拜》</a>給我們的建議），透過降低「身不由己」的比重，增加對生活的掌控感，提高幸福感，應該是個不錯的方向。</p><p>但這題就是一個餘裕題。一樣是4000個禮拜的教誨：我們依然要考慮放棄行事曆上的彈性，換取社群的紅利。</p><p>而我們<a href="https://club.1-know.org/">《一個讀書會》</a>的討論中認為，餘裕的幸福（行事曆上的彈性）跟抱團的幸福（社群的紅利）其實是不同種類的幸福，也許可以理解為「血清素的幸福」跟「催產素的幸福」。</p><h3 id="正確型人才-vs-優異型人才">正確型人才 vs 優異型人才</h3><p>正確型人才講專業、穩定、標準，就是典型的好學生、好員工。華人社會很喜歡這種人，並且也很擅長培養這種人，因為正確型人才容易在「負增強」的教育環境下產生。</p><p>優異型人才講創新、風險、藝術，比較容易自「正增強」下產生。啊，所言極是。</p><h3 id="排序不等式">排序不等式</h3><p>為什麼會有馬太效應？因為「排序不等式」，大家想最大化效果。</p><p>為什麼城鄉差距難以彌補？因為「排序不等式」，政策想最大化效果。</p><p>為什麼「優異型人才」才是合理的打法，因為「排序不等式」！偏科才是自然的方向，可惜華人社會</p><h3 id="選擇偏誤-vs-檢查悖論">選擇偏誤 vs 檢查悖論</h3><p>倖存者偏差跟伯克森悖論都是「選擇偏誤」。檢查悖論不是選擇偏誤。</p><p>選擇偏誤來自我們人為犯下的抽樣缺陷（非隨機），但檢查悖論是就算你完全隨機抽樣了，一樣會出現的反直覺結果（不是一種偏誤，是機率上的事實）。</p><p>總覺得自己平均等公車的時間大於表訂班距，是心理作用嗎？不是，這是是檢查悖論。原理可以思考「隨機在學校抽樣詢問『班上的人數』，最後統計的結果是否能接近事實？」，答案是不會。</p><p>本書提到了伯克森悖論。人真的越帥越渣嗎？可能並不是，只是因為我們在選擇交往對象時，考慮的是「帥度跟渣度」的綜合分數，此時樣本已經陷入了選擇偏誤。</p><h3 id="Other-Good-Points">Other Good Points</h3><ul><li>調研的第一步就是把 Problem 變成 Question</li><li>If you’ve never missed a flight, you’re spending too much time in airports. — 諾貝爾經濟學獎得主 George Stigler 說的，傳達「效率與風險的權衡」。</li><li>vegemite principal：真香定律。</li><li>p.260「灰階思考、黑白決策」其實就是「思圓行方」。</li><li>acedia：對事物毫無關心、無法振作、精神麻木、對生活失去意義感。（我懂，就是多巴胺受體下調的感覺）</li><li>巴菲特選股有 Pygmalion Effect。第一次看到有人用皮格馬利翁效應來描述這件事，感覺其實挺貼切的。</li><li>p.113 給你兩個月想幹麻就幹麻……</li><li>p.164 憑什麼我辛苦二十年，現在卻比別人差……</li><li>p.165 特別是在中國這個有科舉考試傳統的國家，很容易產生一種幻覺，認為「學識應該得到獎勵」……</li><li>有趣的邏輯段子：有一天，三個邏輯學家走進酒館，酒保問：「三位都喝啤酒嗎？」第一位回答：「我不知道」第二位回答「我不知道」第三位回答：「是的」</li><li>結婚是一種股票思維、曖昧是一種期權思維；奮鬥是一種股票思維、演化是一種期權思維。</li></ul>]]></content:encoded>
      
      
      <category domain="https://shuaixin.cc/categories/%E8%AE%80%E6%9B%B8%E7%AD%86%E8%A8%98/">讀書筆記</category>
      
      
      <category domain="https://shuaixin.cc/tags/5%E9%A1%86%E6%98%9F%E6%9B%B8%E7%B1%8D/">5顆星書籍</category>
      
      
      <comments>https://shuaixin.cc/System-Thinking-in-Daily-Life/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>Docker 更換掛載點：將 immich 資料搬遷到外接 SSD</title>
      <link>https://shuaixin.cc/immich-move-to-ssd/</link>
      <guid>https://shuaixin.cc/immich-move-to-ssd/</guid>
      <pubDate>Wed, 05 Nov 2025 16:00:00 GMT</pubDate>
      
        
        
          
          
      <description></description>
          
        
      
      
      
      <content:encoded><![CDATA[<p>docker 更換掛載點其實非常方便，倒不如說這部分就是 docker 會那麼好用的其中一個重要因素。一般來說，我們只要在 <code>docker-compose.yml</code> 中把 volumes 欄位設定一下，重新運行，一切就會像沒事人一樣，無痛搬家。</p><p>隨便拿一個簡單的 docker-compose 來看：</p><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">services:</span></span><br><span class="line">  <span class="attr">glance:</span></span><br><span class="line">    <span class="attr">container_name:</span> <span class="string">glance</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">glanceapp/glance</span></span><br><span class="line">    <span class="attr">restart:</span> <span class="string">unless-stopped</span></span><br><span class="line">    <span class="attr">volumes:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">./config:/app/config</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">./assets:/app/assets</span></span><br><span class="line">    <span class="attr">ports:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="number">5678</span><span class="string">:8080</span></span><br><span class="line">    <span class="attr">env_file:</span> <span class="string">.env</span></span><br></pre></td></tr></table></figure><p>我們可以看到在 volumes 跟 ports 裡面都有著 <code>host:container</code> 這種格式的寫法。在 volumes 中，這就表示你的容器會直接把宿主的 <code>./config</code> 當成 <code>/app/config</code> 來取用。而在 ports 中，你的容器會把宿主的 5678 port 當成自己的 8080 port 來用。</p><p>按照這個邏輯，我們來看一下 immich 的 docker-compose：</p><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">name:</span> <span class="string">immich</span></span><br><span class="line"></span><br><span class="line"><span class="attr">services:</span></span><br><span class="line">  <span class="attr">immich-server:</span></span><br><span class="line">    <span class="attr">container_name:</span> <span class="string">immich_server</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">ghcr.io/immich-app/immich-server:$&#123;IMMICH_VERSION:-release&#125;</span></span><br><span class="line">    <span class="comment"># extends:</span></span><br><span class="line">    <span class="comment">#   file: hwaccel.transcoding.yml</span></span><br><span class="line">    <span class="comment">#   service: cpu # set to one of [nvenc, quicksync, rkmpp, vaapi, vaapi-wsl] for accelerated transcoding</span></span><br><span class="line">    <span class="attr">volumes:</span></span><br><span class="line">      <span class="comment"># Do not edit the next line. If you want to change the media storage location on your system, edit the value of UPLOAD_LOCATION in the .env file</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">$&#123;UPLOAD_LOCATION&#125;:/usr/src/app/upload</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">/etc/localtime:/etc/localtime:ro</span></span><br><span class="line">    <span class="attr">env_file:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">.env</span></span><br><span class="line">    <span class="attr">ports:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">&#x27;2283:2283&#x27;</span></span><br><span class="line">    <span class="attr">depends_on:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">redis</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">database</span></span><br><span class="line">    <span class="attr">restart:</span> <span class="string">always</span></span><br><span class="line">    <span class="attr">healthcheck:</span></span><br><span class="line">      <span class="attr">disable:</span> <span class="literal">false</span></span><br><span class="line"></span><br><span class="line">  <span class="attr">immich-machine-learning:</span></span><br><span class="line">    <span class="comment"># 此處省略</span></span><br><span class="line"></span><br><span class="line">  <span class="attr">redis:</span></span><br><span class="line">    <span class="comment"># 此處省略</span></span><br><span class="line"></span><br><span class="line">  <span class="attr">database:</span></span><br><span class="line">    <span class="attr">container_name:</span> <span class="string">immich_postgres</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">ghcr.io/immich-app/postgres:14-vectorchord0.3.0-pgvectors0.2.0</span></span><br><span class="line">    <span class="attr">environment:</span></span><br><span class="line">      <span class="attr">POSTGRES_PASSWORD:</span> <span class="string">$&#123;DB_PASSWORD&#125;</span></span><br><span class="line">      <span class="attr">POSTGRES_USER:</span> <span class="string">$&#123;DB_USERNAME&#125;</span></span><br><span class="line">      <span class="attr">POSTGRES_DB:</span> <span class="string">$&#123;DB_DATABASE_NAME&#125;</span></span><br><span class="line">      <span class="attr">POSTGRES_INITDB_ARGS:</span> <span class="string">&#x27;--data-checksums&#x27;</span></span><br><span class="line">      <span class="comment"># Uncomment the DB_STORAGE_TYPE: &#x27;HDD&#x27; var if your database isn&#x27;t stored on SSDs</span></span><br><span class="line">      <span class="comment"># DB_STORAGE_TYPE: &#x27;HDD&#x27;</span></span><br><span class="line">    <span class="attr">volumes:</span></span><br><span class="line">      <span class="comment"># Do not edit the next line. If you want to change the database storage location on your system, edit the value of DB_DATA_LOCATION in the .env file</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">$&#123;DB_DATA_LOCATION&#125;:/var/lib/postgresql/data</span></span><br><span class="line">    </span><br><span class="line">    <span class="attr">restart:</span> <span class="string">always</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><p>其中的 <code>${UPLOAD_LOCATION}:/usr/src/app/upload</code> 跟 <code>${DB_DATA_LOCATION}:/var/lib/postgresql/data</code> 就是我們此次要下手的部分。</p><p>在下手之前，我們用 <code>docker compose down</code> 先行停機。</p><p>然而 <code>${UPLOAD_LOCATION}</code> 是環境變數的寫法（為了不要然你直接修改 docker-compose 造成損壞），所以我們要在同資料夾的 <code>.env</code> 中編輯：</p><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># You can find documentation for all the supported env variables at https://immich.app/docs/install/environment-variables</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># The location where your uploaded files are stored</span></span><br><span class="line"><span class="string">UPLOAD_LOCATION=./library</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># The location where your database files are stored. Network shares are not supported for the database</span></span><br><span class="line"><span class="string">DB_DATA_LOCATION=./postgres</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 其他設定不更改，下略。</span></span><br></pre></td></tr></table></figure><p>以我為例，我就把這兩個資料夾分別改成 <code>/mnt/apacer/immich-data/library</code> 跟 <code>/mnt/apacer/immich-data/postgres</code>，是我 SSH 掛載的位置。</p><p>接著透過 rsync 來移動資料：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> rsync -av ./library/ /mnt/storage/immich/library/</span><br><span class="line"><span class="built_in">sudo</span> rsync -av ./postgres/ /mnt/storage/immich/postgres/</span><br></pre></td></tr></table></figure><p>至此設定完成，用 <code>docker compose up -d</code> 來讓 immich 上線。</p><p>因為 immich 會去讀取 UPLOAD_LOCATION 所在位置的儲存空間，重新上線之後，剩餘磁碟空間就會是我們新家的資訊咯。</p><p>以上！</p>]]></content:encoded>
      
      
      <category domain="https://shuaixin.cc/categories/Self-Hosting/">Self Hosting</category>
      
      
      <category domain="https://shuaixin.cc/tags/Docker/">Docker</category>
      
      <category domain="https://shuaixin.cc/tags/immich/">immich</category>
      
      <category domain="https://shuaixin.cc/tags/Self-Hosting/">Self Hosting</category>
      
      
      <comments>https://shuaixin.cc/immich-move-to-ssd/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>在 Windows 系統上架設 NTP 伺服器</title>
      <link>https://shuaixin.cc/TMS-NTP-Windows/</link>
      <guid>https://shuaixin.cc/TMS-NTP-Windows/</guid>
      <pubDate>Wed, 15 Oct 2025 16:00:00 GMT</pubDate>
      
        
        
          
          
      <description></description>
          
        
      
      
      
      <content:encoded><![CDATA[<h2 id="需求背景">需求背景</h2><p>此例中，我們要替電影院架設 TMS 系統，所以我們會有一台作為中控的 Windows 電腦，跟數台放在各個影廳的投影機伺服器。</p><p>一般來說，設備只要能上網，時間就能透過網際網路定時進行校準，一片蛋糕。但電影院的投影機伺服器為了做到內容保護，在 DCI 認證的規範之下，通常就只用封閉的內網來進行控制、傳輸與播放，於是我們就得迂迴地提供正確的時間給它們。</p><p>如果我們的中控電腦有兩張網卡，一張上網去讀時間，一張內網作為 NTP 伺服器，把時間資訊傳給投影機們如何？</p><p>挺不賴的，我們開搞。</p><h2 id="安裝-NetTime">安裝 NetTime</h2><p>雖然 Windows 系統本身就自帶 NTP 的功能，但使用方式有點不直觀，本文選用簡單快速的第三方小工具 NetTime。</p><p>安裝開啟後，程式就可以開始從網路上抓取時間進行校準。此時我們進入設定：</p><p><img src="/TMS-NTP-Windows/ntp1.png" alt="ntp1"></p><p>把 <code>Allow other computers to sync to this computer</code> 的選項打開，化身為 server：</p><p><img src="/TMS-NTP-Windows/ntp2.png" alt="ntp2"></p><p>噠啦，就是那麼簡單。</p><h2 id="防火牆設定">防火牆設定</h2><p>至此，Windows 電腦已經可以作為 client 從外網讀取正確時間，並同時作為 server 提供該時間給內網中的其他設備。</p><p>說是這樣說，但我們此處需要的 port 在防火牆設置中並沒有預設開啟。為了讓投影機伺服器們可以傳 request 進來，我們要去手動打通這條路。</p><p>設定位置以 Win11 為例，在控制台 &gt; 系統及安全性 &gt; Windows Defender 防火牆 &gt; 進階設定 &gt; 輸入規則 &gt; 新增規則。</p><p><img src="/TMS-NTP-Windows/ntp3.png" alt="ntp3"></p><p>NTP 走的是 UDP 的 123 port，透過新增規則的精靈即可簡單地設置完成。</p><p>但我們選擇裝逼一波，用命令提示字元來搞定：</p><figure class="highlight cmd"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">netsh advfirewall firewall add rule name=&quot;Allow NTP Server&quot; <span class="built_in">dir</span>=<span class="keyword">in</span> action=allow protocol=UDP localport=<span class="number">123</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><p>此時我們就可以在規則中看到我們開通的 port 了：</p><p><img src="/TMS-NTP-Windows/ntp4.png" alt="ntp4"></p><h2 id="client-端設定">client 端設定</h2><p>最後，我們到各個投影機伺服器的後台，把中控電腦的 IP 位置設為 NTP Server 即告完成。</p><p>你問為何不用特別設定走 UDP 或是特別指定埠號？因為 NTP 幾乎都走 UDP 123，就不費心讓你設定了。</p><p>以上！</p>]]></content:encoded>
      
      
      <category domain="https://shuaixin.cc/categories/%E5%85%B6%E4%BB%96/">其他</category>
      
      
      <category domain="https://shuaixin.cc/tags/TMS/">TMS</category>
      
      <category domain="https://shuaixin.cc/tags/NTP/">NTP</category>
      
      <category domain="https://shuaixin.cc/tags/NetTime/">NetTime</category>
      
      <category domain="https://shuaixin.cc/tags/Windows/">Windows</category>
      
      
      <comments>https://shuaixin.cc/TMS-NTP-Windows/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>讀書筆記：《致富心態》（金錢心理學）</title>
      <link>https://shuaixin.cc/The-Psychology-of-Money/</link>
      <guid>https://shuaixin.cc/The-Psychology-of-Money/</guid>
      <pubDate>Sat, 11 Oct 2025 16:00:00 GMT</pubDate>
      
        
        
          
          
      <description></description>
          
        
      
      
      
      <content:encoded><![CDATA[<p><img src="/The-Psychology-of-Money/zhifuxintai.png" alt="image-20251012172805545"></p><h3 id="沒有人真的是瘋子">沒有人真的是瘋子</h3><p>指數基金的歷史不到五十年、避險基金才差不多二十五年，房屋貸款、信用卡、汽車貸款都是二戰後才出現。美國401退休金賬戶在 1978 開始運行，台灣勞退則是 1986——都只是初生之犢。所以我們如果做出奇怪的財務決策，那也是在所難免。（而因為入不敷出，台灣在 2005 年改成了新制。）</p><p>比如說，美國人購買樂透的金額，超過電影、遊戲、音樂、體育、書籍的消費<strong>總額</strong>。並且，樂透的消費群體，主要集中在收入最低的那群人。書上的數據是，最低收入家庭平均每年花四百美元在買樂透，但四成的美國人遇到緊急事故時卻湊不出四百美元，所以整體而言，花四百美元買樂透的人跟湊不出四百美元的人，是同一群人。</p><p>但他們真的是瘋子嗎？如果我們用他們的角度來看，也許也沒那麼奇怪，買樂透可能是他們唯一能擁抱美夢的時刻了。</p><h3 id="運氣與風險">運氣與風險</h3><p>作者問諾貝爾經濟學獎得主 Robert Shiller 有什麼關於投資我們無法參透的道理，他認為是「<strong>運氣</strong>在投資成功的結果中所扮演的確切作用」。</p><p>鐵路巨擘康內留斯·范德比爾特（Cornelius Vanderbilt）成就斐然，但他幾乎每一筆商業交易都違反法律，不過成敗論英雄，我們現在稱讚他「大膽」。可是我們轉頭看看安隆（Enron），現在卻是一個負面教材。</p><p>2006 年祖克伯拒絕了 Yahoo 的高額收購，現在看來是一樁美談。但 Yahoo 在衰敗之前，也曾拒絕過微軟的高額收購要約，但現在看來就是個笑話。所以我們應該跟誰學習呢？沒人知道。</p><p>（BTW，要約跟邀約是不一樣的喲，要約是一旦 Yahoo 同意，該買賣在法律上直接生效）</p><p>對此，作者的建議是：留意自己讚揚、欣賞的對象，不要太聚焦於特定案例，要關注更廣泛適用的模式。</p><h3 id="貪得無厭">貪得無厭</h3><p>如果你已經擁有足以支應每一項合理需求的能力時，記住幾點：</p><p><strong>最困難的理財技能是在實現目標後停止繼續追逐</strong>、社會比較是問題的核心（總是有人比你更成功更有錢）、有許多事情無論潛在的獲益多龐大，依然不值得冒險。</p><h3 id="讓人混淆的複利">讓人混淆的複利</h3><p>此書書寫當下，巴菲特身價 845 億，但其中有 842 億是他在五十歲後才得到的。如果我們把他的成功都歸功於「精明的投資」，那就重點誤了。真正的關鍵是，他在「七十五年以來」都在進行精明的投資。</p><p>關於巴菲特的成功，書名應該要叫《這傢伙已經持續投資七十五年了》。而探討經濟跟交易的書，應該要出一本《Shut Up And Wait》。</p><h3 id="長尾效應？">長尾效應？</h3><blockquote><p>我已經幹這行三十年了。依我看，簡單的原理就是，有些案子會成功，有些不會。沒有必要反覆研究哪個會成功，只要繼續進行下一個案子就是了。</p><p>——Brad Pitt 的某次得獎感言</p></blockquote><p>我發現目前大家容易把「20-80法則」跟「長尾效應」混淆使用。雖然兩者都是從「冪律分佈」提煉出來的總結，但彼此強調的重點不同：「20-80法則」強調的是頭部的少部分創造的大面積，而「長尾效應」強調的是延綿不絕的、那雖然趨近於零但不等於零的尾部，其看似影響極小，但實際積分起來會發現總面積並不會輸給頭部。</p><p>這本書也犯了這個錯誤，其實這個章節敘述的是「20-80法則」，不是長尾效應。</p><p>不過實際上，原文的章節名稱是「Tails, You Win」，陸譯也比較精准地翻譯成「尾部的勝利」。</p><h3 id="金錢能給我們最好的紅利就是「掌控時間」">金錢能給我們最好的紅利就是「掌控時間」</h3><p>心理學家 Campbell 指出：與任何客觀生活條件相比，<strong>「掌控自己生活的感受」才是預測幸福感的可靠指標</strong>。</p><p>而金錢提供給我們最好的紅利是：在我們想要的時間、與我們想要的人一起做想做的事。</p><p>根據以上兩點，有錢就應該幸福。但根據美國的情形，看起來並不是這樣。</p><p>心理學中有所謂的對抗心理（reactance），就是當我們選擇權被剝奪時，會感到反感並產生反向行為動機（唱反調）。我們在<a href="https://shuaixin.cc/%E8%AE%80%E6%9B%B8%E7%AD%86%E8%A8%98-%E5%8F%AA%E5%B7%A5%E4%BD%9C%E4%B8%8D%E4%B8%8A%E7%8F%AD%E7%9A%84%E8%87%AA%E4%B8%BB%E4%BA%BA%E7%94%9F/">《只工作不上班的自主人生》</a>看過這個概念，就是<strong>自主性</strong>被剝奪。</p><p>作者認為，這跟現代的工作性質變化有關。現代的工作性質偏向勞心、智力工作，比起以前的勞力工作可以在下班後徹底切換到下班模式，現在則很難在下班後切割。於是，我們在時間上的掌控感變低了，自主性被剝奪了，導致我們幸福感下降。</p><p>作者建議，這題解法不容易，但我們要認清重點：掌控你的時間，就是金錢付給你最高的紅利。</p><h3 id="跑車車主的謬論（陸譯：豪車悖論）">跑車車主的謬論（陸譯：豪車悖論）</h3><p>當我們看到一輛名車駛過，我們其實想的是「哇，如果我有這輛車，大家一定會覺得我很酷」，而不是「哇，開這輛車的傢伙真酷」。</p><p>弔詭的點就在這裡。你明明想借由名車來讓別人羨慕，但真實的情況是，其實群眾們根本不在意車主是誰，只是看著車並幻想著自己做在駕駛座上的畫面。</p><p>我們要理解一件事：我們可能「以為」自己想要擁有豪車名錶，但我們真正想得到的是別人的尊敬與羨慕。但事實上，豪車名錶並不能帶來尊重。羨慕的部分也不是羨慕「你」，而是你的「豪車」。</p><h3 id="「有錢」和「富有」">「有錢」和「富有」</h3><p>「富有」（wealthy）是在看不見的地方，看得到的是「有錢」（rich）。也因為這樣，「有錢」這個狀態被我們爭相吹捧，並學習「有錢」的行為模式。但作者提醒，我們要學的是富有。</p><p>相比現在大宗的建議，重投資而輕儲蓄（畢竟儲蓄難敵通膨的侵蝕），但作者強調存錢，因為存錢可以增加選擇權。</p><p>根據作者的概念，如果現金流帶來了「rich」，但沒有增加選擇權，那就不是「wealthy」。此時就可以 callback 回去前面關於幸福跟「掌控生活的感受」正相關的這個部分，如果你的「rich」反而讓你失去了對生活的掌控，那就純純地本末倒置。</p><h3 id="「合理」大於「理性」">「合理」大於「理性」</h3><p>原文的字眼分別為 Reasonable 跟 Rational。</p><p>合乎情理勝過絕對理性，何以可能？作者指出，合情理可以提高堅持率，變相增加成功率。例如，比起國際金融產品，我們可能更偏好買本土企業的股票，即使報酬率從理性上來看比較差。但當波動發生時，因為我們瞭解我們的投資內容，從而有信心上的加持，比較不容易隨意拋售，帶來了後續反敗為勝的可能（也通常會）。</p><p>試想，其實很多投資的原理都是把錢交給不認識的陌生人去運用管理，要是對陌生人的熟悉度有助於強化對這些人的支持，那就是「合理」的做法。</p><p>當然這不僅限理財方面，找一個效果不是最佳但自己喜歡的、能堅持的運動，也是同理。</p><p>所以作者並不是提倡只儲蓄不投資，而是每個人適合不同的理財方式。作者給出的建議是：<strong>使用可以幫助你一夜好眠的方式理財</strong>。</p><h3 id="沒有白吃的午餐">沒有白吃的午餐</h3><p>試想你現在想要一台車。此時，你可以花大錢買一輛新車、花小錢買一輛二手車、或乾脆直接偷一輛——大部分人不會選擇用偷的，因為我們不想承擔被抓後的風險。</p><p>試想你要投資。此時，你可以選擇接受波動性與動蕩（較大代價）、選擇不缺性較低但報酬較低的資產（較小代價），或你可以試圖化身竊車大盜——試著一邊賺進報酬，一邊避開波動。</p><p>為什麼作為消費者，我們知道天下沒有白吃的午餐，願意為了代價付費，但作為投資者，卻想用「偷」的呢？作者指出，消費時我們可以看到標價，凡事皆有其價格，我們欣然接受；但投資時，我們看到的「下跌」感覺就像是被「懲罰」了，就像是我們做錯事一般。</p><p>作者提醒，我們要把市場波動看做手續費，而非罰款。</p><h3 id="Other-Good-Points">Other Good Points</h3><ul><li>經濟學家 Bhashkar Mazumder 的研究顯示，手足之間的「收入相關性」比「身高相關性」或是「體重相關性」還要來得高。</li><li>根據聯準會統計，27%大學畢業生投入了非本科相關的職缺、29%留在家中的父母（家庭主夫、婦）有大學學位。</li></ul>]]></content:encoded>
      
      
      <category domain="https://shuaixin.cc/categories/%E8%AE%80%E6%9B%B8%E7%AD%86%E8%A8%98/">讀書筆記</category>
      
      
      <category domain="https://shuaixin.cc/tags/%E9%87%91%E8%9E%8D/">金融</category>
      
      <category domain="https://shuaixin.cc/tags/4%E9%A1%86%E6%98%9F%E6%9B%B8%E7%B1%8D/">4顆星書籍</category>
      
      
      <comments>https://shuaixin.cc/The-Psychology-of-Money/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>透過 GPIO 來控制 BrightSign 播放器</title>
      <link>https://shuaixin.cc/BrightSign-GPIO/</link>
      <guid>https://shuaixin.cc/BrightSign-GPIO/</guid>
      <pubDate>Mon, 06 Oct 2025 16:00:00 GMT</pubDate>
      
        
        
          
          
      <description></description>
          
        
      
      
      
      <content:encoded><![CDATA[<p>本文我們來實作可以進行互動的螢幕。怎麼個互動法？這次以兩種為例：</p><ul><li>透過 RFID ，刷卡感應後，讓本來循環播放 A 影片的螢幕，改為播放 B 影片。</li><li>透過超聲波回聲判斷，人靠近（或手懸浮在感應區域）時，讓本來循環播放 A 影片的螢幕，改為播放 B 影片。</li></ul><p>為了達到以上效果，我們這次需要的設備除了顯示器以外還需要：</p><ul><li>數位看板播放器（Digital Signage Players），此處我們選用 BrightSign 的 HD225。</li><li>感應 RFID 並回傳訊號的傳感設備。此處我們不買現成產品，選用微控制器 ESP-WROOM-32 + RFID 傳感模塊 MFRC522 來土炮一個。</li><li>感應超聲波並回傳訊號的傳感設備。此處我們也不買現成產品，選用微控制器 NodeMCU + 超聲波傳感模塊 HCSR04 來土炮一個。</li></ul><h2 id="RFID-互動螢幕">RFID 互動螢幕</h2><p>我們的邏輯很簡單：RFID 模塊感應讀取輸入，把 ID 傳入 ESP-WROOM-32 判斷，如果是我們要的 ID，則輸出高電平訊號。當 HD225 讀到高電平訊號傳入，觸發後續影像內容。</p><p>首先來搞定 RFID 的部分。我們 ESP-WROOM-32 使用 Arduino IDE 來進行編譯跟燒錄，所以有幾個前置準備事項：</p><ul><li>在 Preference 中的 Additional boards manager URLs 中填入 <code>https://dl.espressif.com/dl/package_esp32_index.json</code><br><img src="/BrightSign-GPIO/brightsign6.jpg" alt="brightsign6"></li><li>Board Manager 搜尋 esp32，找到 <code>esp32 by Espressif Systems</code>，安裝它<br><img src="/BrightSign-GPIO/brightsign5.jpg" alt="brightsign5"></li><li>Board 我們選擇 <code>ESP32 Dev Module</code><br><img src="/BrightSign-GPIO/brightsign3.jpg" alt="brightsign3"></li><li>Library 搜尋 MFRC522，找到 <code>MFRC522 by GithubCommunity</code>，安裝它</li></ul><p>然後找出我們這顆控制器的腳位圖：</p><p><img src="/BrightSign-GPIO/wroom-32.webp" alt="wroom-32"></p><p>對照腳位，把 MFRC522 接上：</p><ul><li>SCK 接入 GPIO18</li><li>MOSI 跟 MISO 分別接入 GPIO23、GPIO19</li><li>IRQ 我們此例用不到，不接</li><li>3.3V 跟 GND 按圖接入</li><li>SDA 與 RST 可隨選</li></ul><p>然後我們就可以開始編程了。程式內容請參考：</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;SPI.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;MFRC522.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> SS_PIN 5     <span class="comment">// SDA</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> RST_PIN 15   <span class="comment">// RST</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> LED 25</span></span><br><span class="line"></span><br><span class="line"><span class="function">MFRC522 <span class="title">mfrc522</span><span class="params">(SS_PIN, RST_PIN)</span></span>;  <span class="comment">// 建立 RFID 物件</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">setup</span><span class="params">()</span> </span>&#123;</span><br><span class="line">  Serial.<span class="built_in">begin</span>(<span class="number">9600</span>);</span><br><span class="line">  SPI.<span class="built_in">begin</span>();              <span class="comment">// 啟動 SPI</span></span><br><span class="line">  mfrc<span class="number">522.</span><span class="built_in">PCD_Init</span>();       <span class="comment">// 初始化 RC522</span></span><br><span class="line">  <span class="built_in">pinMode</span>(LED, OUTPUT);</span><br><span class="line">  Serial.<span class="built_in">println</span>(<span class="string">&quot;Start reading!&quot;</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">loop</span><span class="params">()</span> </span>&#123;</span><br><span class="line">  <span class="comment">// 檢查是否有新卡片</span></span><br><span class="line">  <span class="keyword">if</span> (!mfrc<span class="number">522.</span><span class="built_in">PICC_IsNewCardPresent</span>()) <span class="keyword">return</span>;</span><br><span class="line">  <span class="comment">// 檢查是否能讀到卡</span></span><br><span class="line">  <span class="keyword">if</span> (!mfrc<span class="number">522.</span><span class="built_in">PICC_ReadCardSerial</span>()) <span class="keyword">return</span>;</span><br><span class="line"></span><br><span class="line">  String uidStr = <span class="string">&quot;&quot;</span>;</span><br><span class="line">  <span class="keyword">for</span> (byte i = <span class="number">0</span>; i &lt; mfrc<span class="number">522.</span>uid.size; i++) &#123;</span><br><span class="line">    <span class="keyword">if</span> (mfrc<span class="number">522.</span>uid.uidByte[i] &lt; <span class="number">0x10</span>) uidStr += <span class="string">&quot;0&quot;</span>;  <span class="comment">// 補0對齊</span></span><br><span class="line">   uidStr += <span class="built_in">String</span>(mfrc<span class="number">522.</span>uid.uidByte[i], HEX);</span><br><span class="line">  &#125;</span><br><span class="line">  uidStr.<span class="built_in">toUpperCase</span>();  <span class="comment">// 讓輸出一致是大寫</span></span><br><span class="line"></span><br><span class="line">  Serial.<span class="built_in">print</span>(<span class="string">&quot;卡片 UID：&quot;</span>);</span><br><span class="line">  Serial.<span class="built_in">println</span>(uidStr);</span><br><span class="line">  <span class="keyword">if</span>(uidStr == <span class="string">&quot;445A478A&quot;</span>)&#123;</span><br><span class="line">    <span class="built_in">digitalWrite</span>(LED, HIGH);</span><br><span class="line">    <span class="built_in">delay</span>(<span class="number">1000</span>);</span><br><span class="line">    <span class="built_in">digitalWrite</span>(LED, LOW);</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="comment">// 停用卡片</span></span><br><span class="line">  mfrc<span class="number">522.</span><span class="built_in">PICC_HaltA</span>();</span><br><span class="line">  <span class="built_in">delay</span>(<span class="number">500</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>其中，<code>LED</code> 的腳位在接入 HD225 之前就是接著 LED 來進行測試。當 LED 點亮，就表示該腳位輸出了 3.3v 高電平。後來就懶得改變數名稱了，看得懂就好 :)</p><p>傳感器完成後，我們將該輸出腳位接到 HD225 的 GPIO 上。（為了這個需要，我們必須另外準備 pitch 為 3.5mm 的端子座。官方建議買 4 或 6 pin 的，因為 12 pin 會很難拆）除了輸出腳位以外，記得還要共地，所以 ESP 的 GND 也要接一條到 HD225 的 GND。</p><p>最後我們到 HD225 的控制後台 BrightAuthor:connected 進行設定。因為我把上述 LED 腳位接入 HD225 的第六 pin，根據對應，我們要設定 BUTTON 3。腳位請參考：</p><p><img src="/BrightSign-GPIO/brightsign2.jpg" alt="brightsign2"></p><p>將 BUTTON 3 的 Trigger Event On Button 設定為 Down，就會在高電平的時候觸發該判斷。至於為什麼他要預設你的 GPIO 接的是按鈕，我也覺得這樣頗誤導人。</p><p><img src="/BrightSign-GPIO/brightsign1.jpg" alt="brightsign1"></p><p>至此，設置完畢！</p><h2 id="超聲波互動螢幕">超聲波互動螢幕</h2><p>一樣先捋一捋邏輯：超聲波模塊持續感應是否有物體靠近，當有東西靠近到足夠距離，請 NodeMCU 送出一個高電平訊號。當 HD225 讀到高電平訊號傳入，觸發後續影像內容。</p><p>首先來搞定超聲波測距的部分。我們 NodeMCU 一樣使用 Arduino IDE 來進行編譯跟燒錄，所以有幾個前置準備事項：</p><ul><li>在 Preference 中的 Additional boards manager URLs 中填入 <code>http://arduino.esp8266.com/stable/package_esp8266com_index.json</code></li><li>Board Manager 安裝 <code>esp8266 by ESP8266 community</code></li><li>Board 我們選擇 <code>NodeMCU v1.0</code></li><li>Library 裝<a href="https://github.com/jeremylindsayni/Bifrost.Arduino.Sensors.HCSR04">Bifrost.Arduino.Sensors.HCSR04</a></li></ul><p>接線與程式部分：</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;hcsr04.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> TRIG_PIN D2</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> ECHO_PIN D1</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> LED D5</span></span><br><span class="line"></span><br><span class="line"><span class="function">HCSR04 <span class="title">hcsr04</span><span class="params">(TRIG_PIN, ECHO_PIN, <span class="number">20</span>, <span class="number">4000</span>)</span></span>;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">setup</span><span class="params">()</span></span>&#123;</span><br><span class="line">    Serial.<span class="built_in">begin</span>(<span class="number">9600</span>);</span><br><span class="line">    <span class="built_in">pinMode</span>(LED, OUTPUT);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">loop</span><span class="params">()</span> </span>&#123;</span><br><span class="line">  <span class="type">int</span> distance = hcsr<span class="number">04.</span><span class="built_in">distanceInMillimeters</span>();</span><br><span class="line">Serial.<span class="built_in">println</span>(distance);</span><br><span class="line">  <span class="keyword">if</span>(distance&lt;<span class="number">50</span>)&#123;</span><br><span class="line">    <span class="built_in">digitalWrite</span>(LED, HIGH);</span><br><span class="line">  &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">    <span class="built_in">digitalWrite</span>(LED, LOW);</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="built_in">delay</span>(<span class="number">250</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>其中的 <code>LED</code> 比照前例，一開始用 LED 測試，後來直接作為輸出，跟 HD225 溝通。</p><p>控制後台 BrightAuthor:connected 的設定跟前例的邏輯完全一樣，注意腳位不要搞錯就好。</p><p>以上！</p>]]></content:encoded>
      
      
      <category domain="https://shuaixin.cc/categories/%E5%85%B6%E4%BB%96/">其他</category>
      
      
      <category domain="https://shuaixin.cc/tags/ESP32/">ESP32</category>
      
      <category domain="https://shuaixin.cc/tags/BrightSign/">BrightSign</category>
      
      <category domain="https://shuaixin.cc/tags/GPIO/">GPIO</category>
      
      <category domain="https://shuaixin.cc/tags/ESP8266/">ESP8266</category>
      
      <category domain="https://shuaixin.cc/tags/NodeMCU/">NodeMCU</category>
      
      <category domain="https://shuaixin.cc/tags/WROOM/">WROOM</category>
      
      
      <comments>https://shuaixin.cc/BrightSign-GPIO/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>容器化實務操作，以 Taiko-Web 為例</title>
      <link>https://shuaixin.cc/Docker-Taiko-Web/</link>
      <guid>https://shuaixin.cc/Docker-Taiko-Web/</guid>
      <pubDate>Fri, 15 Aug 2025 16:00:00 GMT</pubDate>
      
        
        
          
          
      <description></description>
          
        
      
      
      
      <content:encoded><![CDATA[<p>本篇我們要把一個稍微陳舊的項目 Docker 化，方便沒有 Linux 伺服器的使用者們也可以快速運行服務。</p><p>此處我們選用的服務是 2011 就推出，但在 2020 以降才開始紅起來，但也因此被萬代版權方盯上，後來被全網封殺掉的 bui 製作的 Taiko Web。</p><p>但開源的力量是無比強大，我早已 fork 了一份備份出來，所以依然保有其<a href="https://github.com/Shuai-Xin/taiko-bui-backup">原始碼</a>。開源社群的迷人之處就在這裡，你說是吧。</p><p>該項目是一個大部分使用 JavaScript 刻出來的網頁版太鼓達人模擬器，其透過前端技術就可以讓用戶流暢地遊玩，十分方便，令人印象深刻。但今天我們不討論其服務內容，本篇我們將著重在<strong>將一個運行在 Linux 上的服務給容器化——以便用戶快速自行架設服務，或甚至跨平台運行——的過程</strong>。</p><p>各位可以一邊對照原作者的 <a href="https://github.com/Shuai-Xin/taiko-bui-backup/blob/main/setup.md">manual setup</a>，一邊看我們 dockerfile 的對應做法，方便理解。那我們開始咯。</p><h2 id="安裝過程與重新打包">安裝過程與重新打包</h2><h3 id="Installing-the-requirements">Installing the requirements</h3><p>原始的安裝方式為：</p><blockquote><p>If you have not already done so, install the above-listed software on your server. The following commands were ran on a Debian 10 system, you may need to alter them depending on your OS.</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">su</span><br><span class="line">apt update</span><br><span class="line">apt install git python3-pip nginx</span><br></pre></td></tr></table></figure><p>It is recommended to install these optional packages as well.</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">apt install ffmpeg redis supervisor python3-virtualenv</span><br></pre></td></tr></table></figure></blockquote><p>我們的做法依樣畫葫蘆，就是安裝依賴：</p><figure class="highlight dockerfile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">FROM</span> debian:bookworm</span><br><span class="line"></span><br><span class="line"><span class="keyword">ENV</span> DEBIAN_FRONTEND=noninteractive</span><br><span class="line"></span><br><span class="line"><span class="keyword">RUN</span><span class="language-bash"> apt-get update &amp;&amp; \</span></span><br><span class="line"><span class="language-bash">    apt-get install -y --no-install-recommends \</span></span><br><span class="line"><span class="language-bash">    git python3 python3-pip python3-virtualenv \</span></span><br><span class="line"><span class="language-bash">    nginx ffmpeg redis-server gnupg\</span></span><br><span class="line"><span class="language-bash">    supervisor curl &amp;&amp; \</span></span><br><span class="line"><span class="language-bash">    <span class="built_in">rm</span> -rf /var/lib/apt/lists/*</span></span><br></pre></td></tr></table></figure><p>但可以注意到我們不需要 <code>sudo</code>，因為在 docker 的環境裡面我們本來就是 root。</p><h3 id="Installing-MongoDB">Installing MongoDB</h3><p>原始的安裝方式為：</p><blockquote><p>Consult the <a href="https://web.archive.org/web/20221001162951/https://docs.mongodb.com/manual/installation/">MongoDB installation tutorial</a> for your operating system to install MongoDB Community Edition on your system.</p></blockquote><p>簡單來說就是 MongoDB 並不能用 <code>apt-get</code> 的方式來安裝，所以大部分會建議自己去官方那邊慢慢照著指引安裝。近來這種狀況好像越來越常見了，我個人是不太樂見這樣的走勢啦。</p><p>那此時我們如何應對呢？我們這樣做：</p><figure class="highlight dockerfile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">RUN</span><span class="language-bash"> curl -fsSL https://www.mongodb.org/static/pgp/server-8.0.asc | \</span></span><br><span class="line"><span class="language-bash">    gpg -o /usr/share/keyrings/mongodb-server-8.0.gpg --dearmor</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">RUN</span><span class="language-bash"> <span class="built_in">echo</span> <span class="string">&quot;deb [ signed-by=/usr/share/keyrings/mongodb-server-8.0.gpg ] http://repo.mongodb.org/apt/debian bookworm/mongodb-org/8.0 main&quot;</span> \</span></span><br><span class="line"><span class="language-bash">    | <span class="built_in">tee</span> /etc/apt/sources.list.d/mongodb-org-8.0.list</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">RUN</span><span class="language-bash"> apt-get update &amp;&amp; \</span></span><br><span class="line"><span class="language-bash">    apt-get install -y mongodb-org &amp;&amp; \</span></span><br><span class="line"><span class="language-bash">    <span class="built_in">rm</span> -rf /var/lib/apt/lists/*</span></span><br></pre></td></tr></table></figure><p>因為我們 docker 的環境指定了 debian:bookworm，所以我們從 MongoDB 官方那邊找到對應的安裝方式，把指令全部移植過來即是。</p><h3 id="Obtaining-taiko-web">Obtaining taiko-web</h3><p>原始做法：</p><blockquote><p>Next, clone the taiko-web repository into a directory of your choosing.</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">su -c &#x27;mkdir -p /srv/taiko-web&#x27;</span><br><span class="line">su -c &#x27;chown $USER /srv/taiko-web&#x27;</span><br><span class="line">git clone https://github.com/bui/taiko-web.git /srv/taiko-web</span><br></pre></td></tr></table></figure><p>All the commands you run from now on must be ran inside the taiko-web directory, so change your working directory.</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cd /srv/taiko-web</span><br></pre></td></tr></table></figure><p>Run the following commands to install requirements and set default configurations.</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">pip3 install -r requirements.txt</span><br><span class="line">tools/get_version.sh</span><br><span class="line">cp tools/hooks/* .git/hooks/</span><br><span class="line">cp config.example.py config.py</span><br></pre></td></tr></table></figure><p>Edit <a href="http://config.py">config.py</a> in a text editor to configure taiko-web for your system.</p></blockquote><p>我們的做法：</p><figure class="highlight dockerfile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">RUN</span><span class="language-bash"> <span class="built_in">mkdir</span> -p /srv/taiko-web /var/log/taiko-web /data/db</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">RUN</span><span class="language-bash"> git <span class="built_in">clone</span> https://github.com/Shuai-Xin/taiko-bui-backup.git /srv/taiko-web</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">RUN</span><span class="language-bash"> <span class="built_in">cp</span> /srv/taiko-web/config.example.py /srv/taiko-web/config.py</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">RUN</span><span class="language-bash"> pip3 install --break-system-packages --no-cache-dir -r /srv/taiko-web/requirements.txt</span></span><br></pre></td></tr></table></figure><p>幾點差異：</p><ul><li>因為在 docker 中我們是 root，所以不用 <code>chown</code> 來更改權限。</li><li>bui 大大的 repo 已經被封殺了，所以改從我那邊 clone 檔案。</li><li>我們在 pip3 install 中加了 <code>--break-system-packages</code> 的 flag，因為反正我們是專用的環境，沒有在系統管乾不乾淨的，所以套件直接裝在系統層級，不走 venvs。（而因為 <a href="https://peps.python.org/pep-0668/">PEP668</a>，你若不加這個 flag 他會報錯跟你提醒）</li></ul><h3 id="nginx-setup">nginx setup</h3><p>原始做法：</p><blockquote><p>Let’s set up nginx now. Copy the example virtual host file <code>tools/nginx.conf</code> to <code>/etc/nginx/conf.d/taiko-web.conf</code>, changing the <code>server_name</code> and <code>root</code> statements as required.</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">&gt;su -</span><br><span class="line">&gt;cp /srv/taiko-web/tools/nginx.conf /etc/nginx/conf.d/taiko-web.conf</span><br></pre></td></tr></table></figure><p>Next, open <code>/etc/nginx/nginx.conf</code> and comment out the line which displays the default nginx page.</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&gt;include /etc/nginx/sites-enabled/*;</span><br></pre></td></tr></table></figure><p>becomes</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&gt;#include /etc/nginx/sites-enabled/*;</span><br></pre></td></tr></table></figure><p>Then, open <code>/etc/nginx/mime.types</code> and add this line near the bottom:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&gt;application/wasm wasm;</span><br></pre></td></tr></table></figure><p>Once you’ve configured the files, reload nginx (as root). Assuming everything was configured correctly, you shouldn’t get any errors.</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&gt;nginx -s reload</span><br></pre></td></tr></table></figure><p>If you try to access your simulator now, you should get a 502 error. That’s because we haven’t started the app server yet, so let’s do that!</p></blockquote><p>我們的做法：</p><figure class="highlight dockerfile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">RUN</span><span class="language-bash"> <span class="built_in">cp</span> /srv/taiko-web/tools/nginx.conf /etc/nginx/conf.d/taiko-web.conf &amp;&amp; \</span></span><br><span class="line"><span class="language-bash">    sed -i <span class="string">&#x27;s/include \/etc\/nginx\/sites-enabled\/\*;/#include \/etc\/nginx\/sites-enabled\/\*;/&#x27;</span> /etc/nginx/nginx.conf</span></span><br></pre></td></tr></table></figure><p>本來手動修改 config 的流程，我們用 <code>sed</code> 來自動修改。</p><h3 id="taiko-web-setup">taiko-web setup</h3><p>原始：</p><blockquote><p>We’ll first create virtual environments for Python and install the required modules.</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">virtualenv -p python3 /srv/taiko-web/.venv</span><br><span class="line">source /srv/taiko-web/.venv/bin/activate</span><br><span class="line">pip install -r /srv/taiko-web/requirements.txt</span><br><span class="line">deactivate</span><br></pre></td></tr></table></figure><p>It is recommended that you use a process manager such as <a href="https://web.archive.org/web/20221001162951/http://supervisord.org/">Supervisor</a> to keep taiko-web running at all times.</p><p>Copy the example configuration file from <code>tools/supervisor.conf</code> to <code>/etc/supervisor/conf.d/taiko-web.conf</code>, adjusting it as needed.</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">su</span><br><span class="line">mkdir -p /var/log/taiko-web</span><br><span class="line">cp tools/supervisor.conf /etc/supervisor/conf.d/taiko-web.conf</span><br></pre></td></tr></table></figure><p>Then, restart Supervisor (as root).</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">su -</span><br><span class="line">service supervisor restart</span><br></pre></td></tr></table></figure><p>And you can check the status of supervisor with this command, to see if anything went wrong (also as root).</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">supervisorctl status</span><br></pre></td></tr></table></figure><p>We’re almost there! taiko-web has been installed and when you start the database you will be able to run it too, but there will be no default songs. Let’s fix that!</p></blockquote><p>可以注意到這裡開了一個 virtualenv，但我們 docker 環境不管那麼多，所以不理他，我們直接運行：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">RUN printf &quot;[supervisord]\nnodaemon=true\n\</span><br><span class="line">[program:mongod]\ncommand=mongod --bind_ip_all\nautorestart=true\n\</span><br><span class="line">[program:redis]\ncommand=redis-server\nautorestart=true\n\</span><br><span class="line">[program:nginx]\ncommand=nginx -g &#x27;daemon off;&#x27;\nautorestart=true\n\</span><br><span class="line">[program:taiko_app]\ndirectory=/srv/taiko-web\ncommand=gunicorn -b 127.0.0.1:34801 app:app\nautorestart=true\n\</span><br><span class="line">[program:taiko_server]\ndirectory=/srv/taiko-web\ncommand=python3 server.py 34802\nautorestart=true&quot; &gt; /etc/supervisord.conf</span><br><span class="line"></span><br><span class="line">EXPOSE 80</span><br><span class="line"></span><br><span class="line">CMD [&quot;/usr/bin/supervisord&quot;, &quot;-c&quot;, &quot;/etc/supervisord.conf&quot;]</span><br></pre></td></tr></table></figure><h2 id="打包結果與部署">打包結果與部署</h2><p>綜合以上，我們的 dockerfile 就長這樣：</p><figure class="highlight dockerfile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">FROM</span> debian:bookworm</span><br><span class="line"></span><br><span class="line"><span class="keyword">ENV</span> DEBIAN_FRONTEND=noninteractive</span><br><span class="line"></span><br><span class="line"><span class="keyword">RUN</span><span class="language-bash"> apt-get update &amp;&amp; \</span></span><br><span class="line"><span class="language-bash">    apt-get install -y --no-install-recommends \</span></span><br><span class="line"><span class="language-bash">    git python3 python3-pip python3-virtualenv \</span></span><br><span class="line"><span class="language-bash">    nginx ffmpeg redis-server gnupg\</span></span><br><span class="line"><span class="language-bash">    supervisor curl &amp;&amp; \</span></span><br><span class="line"><span class="language-bash">    <span class="built_in">rm</span> -rf /var/lib/apt/lists/*</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">RUN</span><span class="language-bash"> curl -fsSL https://www.mongodb.org/static/pgp/server-8.0.asc | \</span></span><br><span class="line"><span class="language-bash">    gpg -o /usr/share/keyrings/mongodb-server-8.0.gpg --dearmor</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">RUN</span><span class="language-bash"> <span class="built_in">echo</span> <span class="string">&quot;deb [ signed-by=/usr/share/keyrings/mongodb-server-8.0.gpg ] http://repo.mongodb.org/apt/debian bookworm/mongodb-org/8.0 main&quot;</span> \</span></span><br><span class="line"><span class="language-bash">    | <span class="built_in">tee</span> /etc/apt/sources.list.d/mongodb-org-8.0.list</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">RUN</span><span class="language-bash"> apt-get update &amp;&amp; \</span></span><br><span class="line"><span class="language-bash">    apt-get install -y mongodb-org &amp;&amp; \</span></span><br><span class="line"><span class="language-bash">    <span class="built_in">rm</span> -rf /var/lib/apt/lists/*</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">RUN</span><span class="language-bash"> <span class="built_in">mkdir</span> -p /srv/taiko-web /var/log/taiko-web /data/db</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">RUN</span><span class="language-bash"> git <span class="built_in">clone</span> https://github.com/Shuai-Xin/taiko-bui-backup.git /srv/taiko-web</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">RUN</span><span class="language-bash"> <span class="built_in">cp</span> /srv/taiko-web/config.example.py /srv/taiko-web/config.py</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">RUN</span><span class="language-bash"> pip3 install --break-system-packages --no-cache-dir -r /srv/taiko-web/requirements.txt</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">RUN</span><span class="language-bash"> <span class="built_in">cp</span> /srv/taiko-web/tools/nginx.conf /etc/nginx/conf.d/taiko-web.conf &amp;&amp; \</span></span><br><span class="line"><span class="language-bash">    sed -i <span class="string">&#x27;s/include \/etc\/nginx\/sites-enabled\/\*;/#include \/etc\/nginx\/sites-enabled\/\*;/&#x27;</span> /etc/nginx/nginx.conf</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">RUN</span><span class="language-bash"> <span class="built_in">printf</span> <span class="string">&quot;[supervisord]\nnodaemon=true\n\</span></span></span><br><span class="line"><span class="string"><span class="language-bash">[program:mongod]\ncommand=mongod --bind_ip_all\nautorestart=true\n\</span></span></span><br><span class="line"><span class="string"><span class="language-bash">[program:redis]\ncommand=redis-server\nautorestart=true\n\</span></span></span><br><span class="line"><span class="string"><span class="language-bash">[program:nginx]\ncommand=nginx -g &#x27;daemon off;&#x27;\nautorestart=true\n\</span></span></span><br><span class="line"><span class="string"><span class="language-bash">[program:taiko_app]\ndirectory=/srv/taiko-web\ncommand=gunicorn -b 127.0.0.1:34801 app:app\nautorestart=true\n\</span></span></span><br><span class="line"><span class="string"><span class="language-bash">[program:taiko_server]\ndirectory=/srv/taiko-web\ncommand=python3 server.py 34802\nautorestart=true&quot;</span> &gt; /etc/supervisord.conf</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">EXPOSE</span> <span class="number">80</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">CMD</span><span class="language-bash"> [<span class="string">&quot;/usr/bin/supervisord&quot;</span>, <span class="string">&quot;-c&quot;</span>, <span class="string">&quot;/etc/supervisord.conf&quot;</span>]</span></span><br></pre></td></tr></table></figure><p>部署的方式就非常簡單了，只要在有 docker 的環境中，將以上檔案存檔為 <code>Dockerfile</code>（記得大寫），並在該資料夾中執行 <code>docker build -t taiko-web .</code>，上述的步驟就全部幫你做好，打包成一個 image，並且只要你是 x86 架構的電腦，就都能成。</p><p>至於你問 ARM 架構為什麼不行？主要是 MongoDB 的問題，因為 docker 指定了 debian，所以 Mongo 就給你 x86 的版本的檔案。那是不是 Mongo 開另一個 container 就可以？是這樣的沒錯，因為 MongoDB 有提供 ARM 架構的 image，這部分可以留給讀者作為練習。（欸）</p><p>最後，我們 <code>docker run -d -p 80:80 --name taiko-web taiko-web</code> 來運行這個 image，伺服器就此上線。此時就可以用該設備訪問 <code>http://localhost</code>，或是用同內網的設備使用瀏覽器訪問 <code>http://運行docker的設備內網ip位置</code>。</p><p>以上！</p>]]></content:encoded>
      
      
      <category domain="https://shuaixin.cc/categories/Self-Hosting/">Self Hosting</category>
      
      
      <category domain="https://shuaixin.cc/tags/Docker/">Docker</category>
      
      <category domain="https://shuaixin.cc/tags/Self-Hosting/">Self Hosting</category>
      
      <category domain="https://shuaixin.cc/tags/Taiko/">Taiko</category>
      
      
      <comments>https://shuaixin.cc/Docker-Taiko-Web/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>自架推播通知伺服器：ntfy</title>
      <link>https://shuaixin.cc/ntfy/</link>
      <guid>https://shuaixin.cc/ntfy/</guid>
      <pubDate>Sat, 28 Jun 2025 16:00:00 GMT</pubDate>
      
        
        
          
          
      <description></description>
          
        
      
      
      
      <content:encoded><![CDATA[<p>原本我的 NetAlertX 跟 Uptime Kuma 使用的通知方式都是透過 gmail，用 SMTP 的方式，自己寄信給自己。但後來發現，收件箱因為這樣而充滿了一堆通知，十分雜亂也不方便管理。</p><p>所以此篇我們要來架設 ntfy，並將 NetAlertX 跟 Uptime Kuma 的通知方式設定成 ntfy，最終透過 ntfy 的 ios app，從 iPhone 接收通知。</p><h3 id="安裝-ntfy">安裝 ntfy</h3><p>此處我們採用 docker compose 的安裝方式，yaml 如下：</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">services:</span></span><br><span class="line">  <span class="attr">ntfy:</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">binwiederhier/ntfy</span></span><br><span class="line">    <span class="attr">container_name:</span> <span class="string">ntfy</span></span><br><span class="line">    <span class="attr">command:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">serve</span></span><br><span class="line">    <span class="attr">environment:</span></span><br><span class="line">      <span class="attr">TZ:</span> <span class="string">Asia/Taipei</span>    <span class="comment"># optional: set desired timezone</span></span><br><span class="line">      <span class="attr">NTFY_BEHIND_PROXY:</span> <span class="literal">true</span></span><br><span class="line">      <span class="attr">NTFY_BASE_URL:</span> <span class="string">https://your.ntfy.domain</span></span><br><span class="line">      <span class="attr">NTFY_UPSTREAM_BASE_URL:</span> <span class="string">https://ntfy.sh</span></span><br><span class="line">    <span class="attr">user:</span> <span class="number">1000</span><span class="string">:1000</span> <span class="comment"># optional: replace with your own user/group or uid/gid</span></span><br><span class="line">    <span class="attr">volumes:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">/var/cache/ntfy:/var/cache/ntfy</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">/etc/ntfy:/etc/ntfy</span></span><br><span class="line">    <span class="attr">ports:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="number">80</span><span class="string">:80</span></span><br><span class="line">    <span class="attr">healthcheck:</span> <span class="comment"># optional: remember to adapt the host:port to your environment</span></span><br><span class="line">        <span class="attr">test:</span> [<span class="string">&quot;CMD-SHELL&quot;</span>, <span class="string">&quot;wget -q --tries=1 http://localhost:80/v1/health -O - | grep -Eo &#x27;\&quot;healthy\&quot;\\s*:\\s*true&#x27; || exit 1&quot;</span>]</span><br><span class="line">        <span class="attr">interval:</span> <span class="string">60s</span></span><br><span class="line">        <span class="attr">timeout:</span> <span class="string">10s</span></span><br><span class="line">        <span class="attr">retries:</span> <span class="number">3</span></span><br><span class="line">        <span class="attr">start_period:</span> <span class="string">40s</span></span><br><span class="line">    <span class="attr">restart:</span> <span class="string">unless-stopped</span></span><br></pre></td></tr></table></figure><p>其中注意：</p><ul><li><code>NTFY_BEHIND_PROXY: true</code> ：我們後續會透過 proxy manager 來反向代理，所以這個需要特別設 true</li><li><code>NTFY_BASE_URL: https://your.ntfy.domain</code>：這裡就是我們 ios app 從外網接收通知用的 domain（我們出門在外也要收得到通知對吧）</li><li><code>NTFY_UPSTREAM_BASE_URL: https://ntfy.sh</code>：因為 iOS 在「推播通知」的設計原則上，app 通常不允許常駐在後面等通知，除非使用 <strong>APNs (Apple Push Notification Service)</strong> 來進行系統層級的喚醒。但我們自架的 server 並沒有 apple 認證，所以如果不透過 <a href="http://ntfy.sh">ntfy.sh</a> 進行 APN 的推送，我們會延遲很久很久才收到通知。所以此處務必加上這個。但當然，因為這樣，我們的服務其實還是依賴了其他 server。</li></ul><h3 id="設定反向代理">設定反向代理</h3><p>我們透過 Nginx Proxy Manager 來進行反向代理：</p><p><img src="/ntfy/image-20250629192242550.png" alt="image-20250629192242550"></p><ul><li>其中 Domain Names 就是後續 iso app 要使用的網域</li><li>Scheme 要用 http，因為內網裡面就是走 http</li><li>為了實時刷新，Websockets 也要打開</li></ul><h3 id="NetAlertX-設定">NetAlertX 設定</h3><p><img src="/ntfy/image-20250629192714164.png" alt="image-20250629192714164"></p><p>注意因為 NetAlertX 跟 ntfy 一樣都在內網環境中，所以在 NTFY host URL 的部分要填入的是走 http 的 ntfy 內網位置。</p><h3 id="Uptime-Kuma-設定">Uptime Kuma 設定</h3><p><img src="/ntfy/image-20250629192909688.png" alt="image-20250629192909688"></p><p>此處同理。</p><h3 id="iPhone-設定">iPhone 設定</h3><p>iPhone 部分就簡單了，app store 下載安裝 ntfy 後：</p><ul><li>Default server 填入我們一開始設定在 <code>NTFY_BASE_URL</code> 的外網網域</li><li>訂閱你的 topic</li></ul><p>收工！</p>]]></content:encoded>
      
      
      <category domain="https://shuaixin.cc/categories/Self-Hosting/">Self Hosting</category>
      
      
      <category domain="https://shuaixin.cc/tags/Self-Hosting/">Self Hosting</category>
      
      <category domain="https://shuaixin.cc/tags/ntfy/">ntfy</category>
      
      <category domain="https://shuaixin.cc/tags/NetAlertX/">NetAlertX</category>
      
      <category domain="https://shuaixin.cc/tags/Uptime-Kuma/">Uptime Kuma</category>
      
      
      <comments>https://shuaixin.cc/ntfy/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>台語小筆記：留意輕聲，詞義差很多</title>
      <link>https://shuaixin.cc/Taiwanese-2-Neutral-Tone/</link>
      <guid>https://shuaixin.cc/Taiwanese-2-Neutral-Tone/</guid>
      <pubDate>Mon, 23 Jun 2025 16:00:00 GMT</pubDate>
      
        
        
          
          
      <description></description>
          
        
      
      
      
      <content:encoded><![CDATA[<p>台語作為一門標準的聲調語言（tone language），不同的聲調會有不同的意思表達。</p><p>上次回外婆家被催婚，其中就有一句：</p><blockquote><p><code>senn nn̄g-ê--ah gín-ná</code>（生兩個啊gín仔）</p></blockquote><p>我就說好啦，不要急，但<strong>為什麼是兩個</strong>？才知道此處的 <code>nn̄g-ê--ah</code> 跟 <code>nn̄g-ê</code> 的意思可差多了。前者是「兩三個」的意思，而後者是切確的「兩個」。</p><p>讀音上，前者 <code>nn̄g-ê--ah</code> 的 ê 讀輕聲，後者 <code>nn̄g-ê</code> 的 ê 則讀五聲。</p><p>所以如果有人跟你說：</p><blockquote><p><code>lâi  lim nn̄g pue</code>（來喝兩杯）</p></blockquote><p>這裡如果遇到 <code>nn̄g--pue</code>（三聲輕聲）就是喊你來喝個兩三杯，幾杯不重要。但如果遇到的是 <code>nn̄g-pue</code>（三聲一聲），那就真的是指「兩杯」了。</p><h2 id="其他輕聲改變詞義的例子">其他輕聲改變詞義的例子</h2><h4 id="買無">買無</h4><ul><li><code>bué-bô</code>（買不到）</li><li><code>bué--bô</code>（買不買？）</li></ul><h4 id="驚死">驚死</h4><ul><li><code>kiann-sí</code>（害怕死亡）</li><li><code>kiann--sí</code>（嚇死）</li></ul><h4 id="有影無">有影無</h4><ul><li><code>ū-iánn-bô</code>（真的沒有）</li><li><code>ū-iánn--bô</code>（真的假的？）</li></ul>]]></content:encoded>
      
      
      <category domain="https://shuaixin.cc/categories/%E8%AA%9E%E8%A8%80%E7%AD%86%E8%A8%98/">語言筆記</category>
      
      <category domain="https://shuaixin.cc/categories/%E8%AA%9E%E8%A8%80%E7%AD%86%E8%A8%98/%E5%8F%B0%E8%AA%9E%E7%AD%86%E8%A8%98/">台語筆記</category>
      
      
      <category domain="https://shuaixin.cc/tags/%E5%8F%B0%E8%AA%9E/">台語</category>
      
      <category domain="https://shuaixin.cc/tags/%E5%8F%B0%E7%BE%85/">台羅</category>
      
      <category domain="https://shuaixin.cc/tags/%E8%AE%8A%E8%AA%BF/">變調</category>
      
      <category domain="https://shuaixin.cc/tags/%E8%81%B2%E8%AA%BF/">聲調</category>
      
      
      <comments>https://shuaixin.cc/Taiwanese-2-Neutral-Tone/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>智能家居 EP11：用反向代理取代端口轉發（NPM+DuckDNS）</title>
      <link>https://shuaixin.cc/HA-11-Reverse-Proxy/</link>
      <guid>https://shuaixin.cc/HA-11-Reverse-Proxy/</guid>
      <pubDate>Fri, 23 May 2025 16:00:00 GMT</pubDate>
      
        
        
          
          
      <description></description>
          
        
      
      
      
      <content:encoded><![CDATA[<p>我們在 <a href="https://shuaixin.cc/HA-X-Remote/">智能家居 EP9：利用DDNS、通訊埠轉發進行遠端控制</a> 已經透過 Port Forwarding 的方法實現外網訪問，可以成功在外面控制家中設備。</p><p>但實際上，在網路安全的領域中，端口轉發意味著 port 的暴露，其實大家都看得到你有哪些 port 是開的。例如，我用外網透過 nmap 來掃描我家可以看到：</p><p><img src="/HA-11-Reverse-Proxy/nmap.png" alt="nmap"></p><p>開放的 port 那是一個清清楚楚明明白白。</p><p>對此，我們使用 Nginx Proxy Manager （下稱 NPM）來替我們進行反向代理，減少我們直接開 port 的需求。假設我架設了五個服務，本來我要分別開五個 port 來訪問。現在透過 NPM，我可以只開 80 跟 443 出來給 NPM，往後需要訪問什麼服務，通通都去問 NPM，讓 NPM 統一替我們處理請求。這就是所謂的<strong>代理</strong>（proxy）。</p><p><img src="/HA-11-Reverse-Proxy/image-20250525140636301.png" alt="image-20250525140636301"></p><p>在此架構中，NPM 可以運行在與 HA 同網路的另一個設備中、與 HA 同一個設備中的不同容器（如 docker）中、或甚至以 add-on 的形式裝在 HA 身上（該附加元件在<a href="https://github.com/hassio-addons/addon-nginx-proxy-manager">這裡</a>）。而我此處是運行在與 HA 同網路的另一個設備中，可以參考一下我目前的拓撲：</p><p><img src="/HA-11-Reverse-Proxy/shuai-diagram.png" alt="shuai-diagram"></p><h2 id="編輯-configuration-yaml-設定">編輯 <code>configuration.yaml</code> 設定</h2><p>因為 Home Assistant 自帶的安全性策略，在我們親自設定之前，並不會允許 proxy 轉過來的連線請求。所以我們要來編輯一下 <code>configuration.yaml</code>。（至於如何找到並編輯 <code>configuration.yaml</code> 我們在 <a href="https://shuaixin.cc/HA-7-File-Editor/">智能家居 EP7：File Editor </a>有討論過，還請參考。）</p><p>而因為 <a href="https://shuaixin.cc/HA-X-Remote/">智能家居 EP9：利用DDNS、通訊埠轉發進行遠端控制</a> 那時候我們是透過 DuckDNS 替我們弄 SSL 的，所以 <code>configuration.yaml</code> 中本來是：</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">http:</span></span><br><span class="line">  <span class="attr">ssl_certificate:</span> <span class="string">/ssl/fullchain.pem</span></span><br><span class="line">  <span class="attr">ssl_key:</span> <span class="string">/ssl/privkey.pem</span></span><br></pre></td></tr></table></figure><p>但我們現在要把 SSL 的事務交給 NPM，這邊的就要取消掉，變成：</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">http:</span></span><br><span class="line">  <span class="attr">use_x_forwarded_for:</span> <span class="literal">true</span></span><br><span class="line">  <span class="attr">trusted_proxies:</span></span><br><span class="line">    <span class="bullet">-</span> <span class="number">192.168</span><span class="number">.87</span><span class="number">.87</span>  <span class="comment"># ← NPM</span></span><br><span class="line"><span class="comment">#  ssl_certificate: /ssl/fullchain.pem</span></span><br><span class="line"><span class="comment">#  ssl_key: /ssl/privkey.pem</span></span><br></pre></td></tr></table></figure><p>其中的 <code>use_x_forwarded_for</code> 就是允許 proxy 轉發，而 <code>trusted_proxies</code> 就是你 NPM 所在的位置。</p><h2 id="DuckDNS-設定">DuckDNS 設定</h2><p>DDNS 的部分我們一樣繼續使用 DuckDNS 的服務：</p><p><img src="/HA-11-Reverse-Proxy/ddns.png" alt="ddns"></p><p>但一樣到 DuckDNS 在 HA 的附加元件中的設定把 SSL 的服務關閉：</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">lets_encrypt:</span></span><br><span class="line">  <span class="attr">accept_terms:</span> <span class="literal">false</span> <span class="comment"># ← 關掉</span></span><br><span class="line"><span class="comment">#  algo: secp384r1</span></span><br><span class="line"><span class="comment">#  certfile: fullchain.pem</span></span><br><span class="line"><span class="comment">#  keyfile: privkey.pem</span></span><br></pre></td></tr></table></figure><h2 id="Nginx-Proxy-Manager-設定">Nginx Proxy Manager 設定</h2><p>接著我們到 NPM 設定。</p><p>Domain Name 就填入 DuckDNS 申請的域名，以後只有透過這個名字進來的請求，才轉發給 HA。反之，如果直接用 IP 位置訪問，NPM 會說你要做啥，不講清楚我可不讓進。</p><p>Forward Hostname 跟 Forward Port 就是你本來端口轉發的目的（也就是 HA 的位置）。</p><p><img src="/HA-11-Reverse-Proxy/image-20250525153412484.png" alt="image-20250525153412484"></p><p>注意此處的 <strong>scheme 要選擇 http</strong>，這表示連入之後，內網部分就用 http 溝通即可。而 <strong>Websockets Support 必須打開</strong>，因為 HA 的前後端確實是用 websocket 持續溝通的（才能在你關燈之後，不需重新整理就顯示已關閉）。</p><p><img src="/HA-11-Reverse-Proxy/image-20250525153432543.png" alt="image-20250525153432543"></p><p>而 SSL 的部分我們就全部打開。</p><h2 id="關掉端口轉發！">關掉端口轉發！</h2><p>最後，我們本來特別開給 HA 的 port 就可以關掉了。保留 80 跟 443 給 NPM 即可：</p><p><img src="/HA-11-Reverse-Proxy/image-20250525154029751.png" alt="image-20250525154029751"></p><hr><p>如此一來，設定完畢。我們的遠端訪問方式已經從<strong>端口轉發</strong>進階成<strong>反向代理</strong>，除了更安全之外，家中網路的架構也變得更有條有理，再也不需要到處打洞開 port 了。</p><p>不過話說回來，DuckDNS 只有五個域名可以用，那如果我有更多需求的話，有什麼其他選擇嗎？</p><p>嘿，有的，如果你有自己的域名的話，這題就好辦了。有機會再撰文提供大家解法。</p>]]></content:encoded>
      
      
      <category domain="https://shuaixin.cc/categories/%E6%99%BA%E8%83%BD%E5%AE%B6%E5%B1%85/">智能家居</category>
      
      
      <category domain="https://shuaixin.cc/tags/Home-Assistant/">Home Assistant</category>
      
      <category domain="https://shuaixin.cc/tags/Proxy/">Proxy</category>
      
      
      <comments>https://shuaixin.cc/HA-11-Reverse-Proxy/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>讀書筆記：《為何三歲開始說謊？》</title>
      <link>https://shuaixin.cc/Why-3-Lie/</link>
      <guid>https://shuaixin.cc/Why-3-Lie/</guid>
      <pubDate>Sat, 05 Apr 2025 16:00:00 GMT</pubDate>
      
        
        
          
          
      <description></description>
          
        
      
      
      
      <content:encoded><![CDATA[<p><img src="/Why-3-Lie/Why-3-Lie.jpg" alt="Why-3-Lie"></p><h3 id="皮亞傑之前">皮亞傑之前</h3><p>在皮亞傑（大致在1960）之前，人們認為孩童的認知能力跟大人是一樣的，只是缺乏經驗跟知識。</p><p>皮亞傑顛覆大家的看法，表示孩童不是「小大人」，其實認知能力是要漸進發展並建立的。愛因斯坦曾說，皮亞傑的發現跟理論是「天才之作」。</p><h3 id="一歲前就已擁有數感、物理常識、簡單的邏輯">一歲前就已擁有數感、物理常識、簡單的邏輯</h3><p>皮亞傑發現九個月大的孩子才會動手排除遮擋物，找到後方的玩具，所以認為物體恆存是九個月大的里程碑。但後續透過「凝視時間」的觀察，其實五個月大的孩子，就會對違反物體恆存的狀況感到好奇。</p><p>同樣是五個月大，孩子至少具備 1+1 或 2-1 的概念。因為當我們用屏風遮擋一個物品，再放進一個物品，當我們秀出來居然還是只有一個物品，孩子會投以較長的凝視時間。兩個物品遮住，拿出一個後，秀出來還是兩個，一樣會得到較長的凝視時間。</p><p>物體違反地心引力往上飛時、兩物隔空互動時也會。</p><p>甚至，八個月大的孩子有機率的概念。一白四紅的獎池，我們抽出四白一紅給他看，你會得到凝視。</p><h3 id="人腦是多功能瑞士刀，不是通用型處理器">人腦是多功能瑞士刀，不是通用型處理器</h3><p>這個概念我們在<a href="https://shuaixin.cc/%E8%AE%80%E6%9B%B8%E7%AD%86%E8%A8%98-%E6%88%91%E5%80%91%E7%9C%9F%E7%9A%84%E6%9C%89%E8%87%AA%E7%94%B1%E6%84%8F%E5%BF%97%E5%97%8E/">《我們真的有自由意志嗎》</a>就討論過，我們只能學會我們能夠學會的能力。而通常，某個能力就是某個大腦模塊專門負責。如果大腦中沒有某個模塊，那我們就做不到那件事。</p><h3 id="rTPJ：心智理論的腦區">rTPJ：心智理論的腦區</h3><p>擁有心智理論能力代表，你知道他人也擁有心智，並且他人可能擁有錯誤信念。最經典的例子就是，我們在受試者面前打開糖果的包裝，結果裡面是一隻鉛筆，此時我們問：「如果等等小明來了，你覺得他會猜裡面有什麼？」。如果正確回答，表示擁有心智理論能力。</p><p>看似簡單，但三歲的小朋友通常沒轍，平均要到五歲才會通過。</p><p>負責這個能力的腦區就是 rTPJ，我們若用跨顱磁刺激的方式刺激這個區域，可以影響成人對他人行為的道德判斷。（推敲他人意圖的能力受到干擾）</p><h3 id="為何三歲開始說謊？">為何三歲開始說謊？</h3><p>書中雖然在第二章就討論了心智理論，可是在第十章才標題回收。好了，所以為什麼三歲開始說謊呢？就是因為心智理論的能力發展出來了。但是第二章說三歲無法通過糖果測試，但這裡居然又能說謊了？</p><p>這裡我們可以推論，隨著心智理論能力的發展，讓說謊這個行為出現。而隨著心智理論能力的逐漸成熟，說謊的能力也會進步。據書中的例子，三歲孩子雖然會謊報自己沒有偷看盒子，但你只消進一步問盒子裡面有什麼，他會不攻自破。但五歲以上，他會開始圓謊。</p><h3 id="三元共享式注意力">三元共享式注意力</h3><p>一歲大的孩子就會用手指物了，但他是要指給你看嗎？研究認為，是想指給你看沒錯。</p><h3 id="哭鬧要理會嗎？">哭鬧要理會嗎？</h3><p>有一派育兒理論主張，寶寶哭鬧時先不要理會，不可以讓他們覺得只要哭鬧就能解決問題，否則他們會學會這種情緒勒索的招式。</p><p>但這裡指出，如果寶寶跟照顧者之間的社交互動不良，所造成的心理生理壓力會對發展造成負面影響。</p><p>如果真的擔心寶寶學會使用哭鬧來予取予求，等到年紀較大了再進行矯正即可。</p><h3 id="女性憂鬱症比例較高的其中一個可能：MAO">女性憂鬱症比例較高的其中一個可能：MAO</h3><p>MAO 即單胺氧化酶，顧名思義，單胺會被他代謝掉。咱大腦中的血清素跟多巴胺都在其防守范圍內。</p><p>而負責表現 MAO 的基因位於 X 染色體，所以擁有兩條 X 的女生，其 MAO 的表現量也會高於男性。</p><p>從這個因素出發，女性腦中的血清素會比較快地被代謝掉，相對上更有憂鬱的機會。</p><h3 id="三百年未解的哲學問題：視覺跟觸覺的推理">三百年未解的哲學問題：視覺跟觸覺的推理</h3><p>突然恢復視力的天生盲人，能第一次就看出圓形跟方形嗎？</p><p>經驗主義陣營的洛克、伯克萊認為不行，理性主義的萊佈尼茲認為可以。</p><p>2011 由海爾德與辛哈針對先天白內障的復明實驗給出了答案：不行！</p><p>從此這題不再是一個哲學問題。</p><h3 id="Other-Good-Points">Other Good Points</h3><ul><li>語言學習確實有其關鍵期，而開關跟 GABA 也許有關。但為何要關閉關鍵期呢？推測是因為運作期間產生的自由基太多。</li><li>全世界的語言加總起來有 800 多個音素，而嬰兒全部都能分辨出來。但隨著成長（專化），敏銳度就會下降。書上的例子是，日本人的 R、L 不分。</li><li>帕夫洛夫其實是生理學家，研究動物的消化系統得過諾貝爾獎。 流口水的制約，是不小心發現的。</li><li>操作制約的四個元素中，目前專家建議是，管教孩子以「正增強」跟「負懲罰」較為合適。</li><li>因為優生學的流行，整個美國在 20 世紀有六萬人被強迫絕育。</li><li>表觀遺傳學的例子：<ul><li>曾在青春期以前經歷過饑荒的世代，其孫輩死於心血管疾病的機率較低；反過來，孫輩罹患糖尿病的機率多出常人四倍。</li><li>老鼠實驗中，透過氣味與電擊，讓老鼠害怕該氣味。這個記憶，居然透過表觀遺傳的方式，遺傳了下去！（為了避免是爸媽傳授的，甚至是走人工授精，不給教學機會）</li></ul></li></ul>]]></content:encoded>
      
      
      <category domain="https://shuaixin.cc/categories/%E8%AE%80%E6%9B%B8%E7%AD%86%E8%A8%98/">讀書筆記</category>
      
      
      <category domain="https://shuaixin.cc/tags/4%E9%A1%86%E6%98%9F%E6%9B%B8%E7%B1%8D/">4顆星書籍</category>
      
      <category domain="https://shuaixin.cc/tags/%E8%85%A6%E7%A7%91%E5%AD%B8/">腦科學</category>
      
      
      <comments>https://shuaixin.cc/Why-3-Lie/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>抉擇的心法</title>
      <link>https://shuaixin.cc/Decision-Making-Dharma/</link>
      <guid>https://shuaixin.cc/Decision-Making-Dharma/</guid>
      <pubDate>Mon, 17 Mar 2025 16:00:00 GMT</pubDate>
      
        
        
          
          
      <description></description>
          
        
      
      
      
      <content:encoded><![CDATA[<p>讀書會也成立兩年多了。綜合各家智慧，我們統整了此《抉擇的心法》。供猶豫不決中的你一個參考。</p><p><img src="/Decision-Making-Dharma/decision-making-chart.png" alt="decision-making-chart"></p><h2 id="做或不做問題">做或不做問題</h2><p>舉例來說，如果你為「這個活動我該不該報名參加」而煩惱。那根據我們的心法，此時是個「做或不做問題」，建議選做。</p><p>根據<strong>蔡加尼克效應</strong>，相較於已完成的事情，人們更容易惦記著「未完成」的那些。因此，當你選擇「不做」，你可能會一直掛念「如果當初做了，會怎麼樣？」。</p><p>人是很「犯賤」的，<strong>我們往往最忘不掉未竟之事</strong>。（這也是為什麼蔡加尼克效應很常被用來解釋為何淺嘗而止的「初戀」總是最美好最難忘的）</p><p>**《臨終前最後悔的五件事》**書中，在安寧病房工作多年的作者 Bronnie Ware 記錄了許多臨終老人們的心聲，發現他們的後悔大多來自「沒做到的事情」，而非「做了的事」。這說明，<strong>未曾嘗試的遺憾，比做錯了的懊悔更深刻</strong>。</p><p>另外，根據康奈爾大學於1995年發表的研究論文《The Experience of Regret: What, When, and Why》提到：「短期內人們更容易後悔行動（commission errors），但長期內更後悔不行動（omission errors）。」</p><p>其原文為：</p><blockquote><p>“Actions, or errors of commission, generate more regret in the short term; but inactions, or errors of omission, produce more regret in the long run.”</p></blockquote><p>綜合以上，「要是有做就好了」的殺傷力，比「早知道不做了」還要來得大。故在「做或不做問題」，建議選做。</p><h2 id="新舊問題">新舊問題</h2><p>待撰文分析。</p><h2 id="格局問題">格局問題</h2><p>待撰文分析。</p><h2 id="常見問題">常見問題</h2><p><em>有時候選擇「不做」也是一種智慧不是嗎？</em></p><p>此心法的使用時機是當你<strong>猶豫不決</strong>，難以抉擇之時，才有使用的必要。如果當你能夠自行選擇「不做」，那表示在該議題上，你並不需要藉助《抉擇的心法》。</p>]]></content:encoded>
      
      
      <category domain="https://shuaixin.cc/categories/%E5%85%B6%E4%BB%96/">其他</category>
      
      
      
      <comments>https://shuaixin.cc/Decision-Making-Dharma/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>讀書筆記：《知識的錯覺》</title>
      <link>https://shuaixin.cc/The-Knowledge-Illusion/</link>
      <guid>https://shuaixin.cc/The-Knowledge-Illusion/</guid>
      <pubDate>Fri, 14 Mar 2025 16:00:00 GMT</pubDate>
      
        
        
          
          
      <description></description>
          
        
      
      
      
      <content:encoded><![CDATA[<p><img src="/The-Knowledge-Illusion/knowledge.jpg" alt="knowledge"></p><h3 id="超憶症難道不是超能力嗎？">超憶症難道不是超能力嗎？</h3><p>超憶症，擁有超常的情節記憶（我們在《最高學以致用法》討論過記憶的分類），可以記得一生中經歷過的所有事情。聽起來很屌，很像超能力，不是嗎？超強的記憶力，難道不具備十足的演化優勢嗎？</p><p>然而就結果論而言，並不是。（否則記憶力較差的群體應當早就被天擇掉了）</p><p>書中提到，如果這個世界鼓勵投機，那我們將會掌握機率與統計、如果鼓勵演繹推理，那我們將各個都是福爾摩斯。但事實是，我們在這兩方面都是一團糟。相反地，我們演化至今的世界由因果邏輯主導，這也是為什麼，人很擅長於因果分析。</p><p>後見之明告訴我們，人腦在這個世界必須具備的能力，相比「機率統計」、「演繹推理」、「強大的記憶力」，可能更偏向「因果分析」。</p><h3 id="因果推理：不是任何刺激都能形成制約">因果推理：不是任何刺激都能形成制約</h3><p>巴甫洛夫的狗最後對鈴聲（中性刺激）產生了制約，巴甫洛夫認為此處的鈴聲可以替換成任意刺激，都會有效。（即，他認為狗勾沒有去思考兩者之間關係）</p><p>但後來針對老鼠的進一步實驗發現，閃光與電擊、噪音與電擊、糖水與胃痛可以形成制約，但閃光與胃痛、糖水與電擊，就沒辦法。（即，老鼠是有在進行簡易的因果推理的）</p><h3 id="預測性推理-診斷式推理">預測性推理/診斷式推理</h3><p>預測性推理就是「由因推果」，診斷式推理則是「由果推因」。那麼人類比較擅長哪個呢？如同所有其他生物，我們比較擅長預測性推理。</p><p>至於診斷式推理，雖然難以證明，但目前沒有證據可以看出其他動物能夠進行診斷式推理。</p><h3 id="我們把整個世界當做儲存器在用">我們把整個世界當做儲存器在用</h3><p>我們沒有在「運算」。</p><p>如何讓車保持在車道中？我們觀察兩側的標線的移動速度，當一側較慢，那我們就偏向那邊。如何成功從門的中間走進去？我們僅只是確保兩側門框靠近我們的速度是一樣的。接高飛球？我們的確沒有在算拋物線吧？我們直接看。</p><p>老式的人工智慧為何發展有限？因為我們 input 給他盡量多的環境資訊，讓他算拋物線。但人根本不是這樣，相反的，我們眼睛同一時間其實只能看到非常小範圍的內容（我們在《思考不過是一場即興演出》就討論過這個動眼實驗）。</p><h3 id="我們也把身體當做記憶卡在用">我們也把身體當做記憶卡在用</h3><p>有些人認為同性戀是令人反感的、幾乎所有有兄弟姐妹的人都會認為手足間的亂倫十分惡心。然而這些感受是我們用「心智」自行判斷出來的嗎？大概不是，這些是基因透過演化留在我們身上的軀體標記。而這些標記告訴我們這些行為「不對」，於是我們將其敘述為「不道德」。（「厭惡感」是「道德判斷」的驅動器）</p><p>我們看到蜘蛛會害怕、會懼高、看到嘔吐物會反胃、會自發地去遠離看似污穢之物。這些真的是我們用「心智」去思考出來的嗎？大概不是，我們身體自己會做出這些判斷。</p><p>綜合以上，我們不應認為「心智」單純就只是大腦內的抽象運算。其實大腦、身體、外部環境會一起進行記憶、推理、跟決策。</p><p>心智並非附屬於大腦的一部分。恰恰相反，大腦是心智的一部分。</p><h3 id="知識的錯覺">知識的錯覺</h3><p>知識的錯覺就這樣產生了。我們以為我們知道的，遠比我們真的知道的，來得少。原因是，我們其實只知道知識的索引，但真正內化的沒有多少。我們把大部分的知識，存在身體裡（不是大腦裡）、存在世界中（環境資訊，反正需要的時候再取用即可，一切非常自然，導致你以為你知道）、存在別人的大腦裡。</p><p>你以為你知道，但其實只是用索引的方式在記憶！（在《記憶決定你是誰》中，我們確實學過，海馬迴是索引大師，不是記憶大師）</p><p>嘿，Title Drop！</p><h3 id="政治的錯覺">政治的錯覺</h3><p>對於一項公眾議題，「詢問立場」（價值取向）容易得到較為偏激的回答，但進而請求「給出說明」（結果取向）後，會緩和其立場的極端程度。</p><p>但這個「給出說明」必須是「因果性的解釋」而不是「支持某方立場的原因」，因為訴諸個人的理念並沒辦法破解知識的錯覺。</p><p>需要注意的是，要求某人解釋一項他們並不理解的政策不會改善彼此之前的人際關係。揭露人們的錯覺通常會令其惱羞成怒。</p><p>所以民主是好的嗎？可能不是。但目前人類社會還沒有更好的方案可以執行。</p><h3 id="Other-Good-Points">Other Good Points</h3><ul><li>自動化悖論：當我們在某方面過度依賴自動化，人類反而會在改方面上失能。</li><li>道德心理學家海德（Haidt）透過「道德錯愕」的例子主張「道德結論很少基於推理，更多是來自直覺」。道德錯愕最著名的例子是雙重避孕並且不為人知且雙方皆愉快並認為感情增進的兄妹亂倫。另，食用意外身亡的寵物狗也是一例。<ul><li>有些法律確實來自於普遍的道德共識。但透過海德帶給我們的反思，這種法律就經不起推敲。</li><li>那為什麼有些國家可以吃狗？</li></ul></li><li>認知反思測試（CRT, Cognitive Reflection Test) 被設計來看看你是快速地相信直覺，還是會習慣先反思。<ul><li>棒球棒和球的問題：一支棒球棒和一顆棒球的總價是 1.10 美元，棒球棒比棒球貴 1 美元。請問棒球的價格是多少？直覺答案： 0.10 美元；正確答案： 0.05 美元</li><li>製造機器的問題：一台機器需要 5 分鐘製造 5 件產品。如果 100 台機器一起工作，製造 100 件產品需要多久？直覺答案： 100 分鐘；正確答案： 5 分鐘</li><li>荷花池塘的問題：荷花每天的覆蓋面積會增長一倍。如果需要 48 天覆蓋整個池塘，請問覆蓋半個池塘需要多少天？直覺答案： 24 天；正確答案： 47 天</li></ul></li></ul>]]></content:encoded>
      
      
      <category domain="https://shuaixin.cc/categories/%E8%AE%80%E6%9B%B8%E7%AD%86%E8%A8%98/">讀書筆記</category>
      
      
      <category domain="https://shuaixin.cc/tags/3%E9%A1%86%E6%98%9F%E6%9B%B8%E7%B1%8D/">3顆星書籍</category>
      
      
      <comments>https://shuaixin.cc/The-Knowledge-Illusion/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>利用 EasyButton 跟 OneButton 來防彈跳、判斷雙擊、長按</title>
      <link>https://shuaixin.cc/Button-Library-Debounce/</link>
      <guid>https://shuaixin.cc/Button-Library-Debounce/</guid>
      <pubDate>Sun, 09 Mar 2025 16:00:00 GMT</pubDate>
      
        
        
          
          
      <description></description>
          
        
      
      
      
      <content:encoded><![CDATA[<p>一句話解釋按鍵的彈跳：</p><blockquote><p>你來不及放開按鍵之前，程式已經來問第二次了，所以程式不知道你是按了第二次，還是你單純還沒放開。</p></blockquote><p>如果你懶得管那麼多，不妨直接在 loop 裡面加入 <code>delay(100)</code>，避開明顯的彈跳問題。</p><p>如果你想嚴謹一點，那就引用一些現成的庫來用吧。</p><p>（以下用例中，我的 MCU 是 ESP32）</p><h3 id="EasyButton">EasyButton</h3><p>如果你什麼都不要，就只要防彈跳，可以考慮 <a href="https://github.com/evert-arias/EasyButton">EasyButton</a> 這個 library。</p><p>使用方法很簡單，如下：</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;ezButton.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="type">const</span> <span class="type">int</span> led = <span class="number">19</span>;</span><br><span class="line"></span><br><span class="line">ezButton <span class="title function_">btn</span><span class="params">(<span class="number">23</span>)</span>;</span><br><span class="line"></span><br><span class="line"><span class="type">void</span> <span class="title function_">setup</span><span class="params">()</span>&#123;</span><br><span class="line">  pinMode(led, OUTPUT);</span><br><span class="line"><span class="comment">//pinMode(btn, INPUT_PULLUP);  //ezButton已經幫你預設上拉了</span></span><br><span class="line"></span><br><span class="line">  btn.setDebounceTime(<span class="number">50</span>);     <span class="comment">//如果你手速夠快(50ms內點兩下)，你依然可以讓彈跳發生</span></span><br><span class="line">  </span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="type">void</span> <span class="title function_">loop</span><span class="params">()</span> &#123;</span><br><span class="line"></span><br><span class="line">  btn.loop();                       <span class="comment">//ezButton開始讀btn</span></span><br><span class="line"><span class="comment">//bool reading = digitalRead(btn);  //所以不用自己讀</span></span><br><span class="line"></span><br><span class="line">  <span class="keyword">if</span>(btn.isPressed())&#123;              <span class="comment">//如果要放開才觸發就用 isReleased</span></span><br><span class="line">    digitalWrite(led, !digitalRead(led));</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>額外送你判斷按下跟放開的時機，可以讓你在按下就觸發，或是放開才觸發。</p><h3 id="OneButton">OneButton</h3><p>如果你除了基本的防彈跳，還想要可以定義單擊、雙擊、長按，可以考慮 <a href="https://github.com/mathertel/OneButton">OneButton</a>。</p><p>可參考我的範例：</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;OneButton.h&gt;</span></span></span><br><span class="line"></span><br><span class="line">OneButton btn;  <span class="comment">//設btn為一個OneButton物件</span></span><br><span class="line"></span><br><span class="line"><span class="type">const</span> <span class="type">int</span> led = <span class="number">19</span>;</span><br><span class="line"></span><br><span class="line"><span class="type">void</span> <span class="title function_">setup</span><span class="params">()</span> &#123;</span><br><span class="line">  pinMode(led, OUTPUT);</span><br><span class="line"></span><br><span class="line">  btn.setup(     <span class="comment">//設定定義的這個btn</span></span><br><span class="line">  <span class="number">23</span>,            <span class="comment">//設定按鍵pin</span></span><br><span class="line">  INPUT_PULLUP,  <span class="comment">//設定爲上拉</span></span><br><span class="line">  <span class="literal">true</span>           <span class="comment">//按下為LOW</span></span><br><span class="line">  );</span><br><span class="line"></span><br><span class="line">  btn.attachClick(whenSingle); <span class="comment">//單擊行爲</span></span><br><span class="line">  btn.attachDoubleClick(whenDouble); <span class="comment">//雙擊行爲</span></span><br><span class="line">  btn.attachLongPressStart(whenLong); <span class="comment">//長按行爲</span></span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="type">void</span> <span class="title function_">loop</span><span class="params">()</span> &#123;</span><br><span class="line">  btn.tick();   <span class="comment">//loop中一定要寫這個，它才會持續監視按鈕</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="type">void</span> <span class="title function_">whenSingle</span><span class="params">()</span>&#123;</span><br><span class="line">  digitalWrite(led, !digitalRead(led));</span><br><span class="line">&#125;</span><br><span class="line"><span class="type">void</span> <span class="title function_">whenDouble</span><span class="params">()</span>&#123;</span><br><span class="line">  digitalWrite(led, !digitalRead(led));</span><br><span class="line">&#125;</span><br><span class="line"><span class="type">void</span> <span class="title function_">whenLong</span><span class="params">()</span>&#123;</span><br><span class="line">  digitalWrite(led, !digitalRead(led));</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>此例中，我單擊、雙擊、長按都觸發一樣的動作，你可以自己定義要分別做什麼動作。</p>]]></content:encoded>
      
      
      <category domain="https://shuaixin.cc/categories/%E5%85%B6%E4%BB%96/">其他</category>
      
      
      <category domain="https://shuaixin.cc/tags/ESP32/">ESP32</category>
      
      <category domain="https://shuaixin.cc/tags/Arduino/">Arduino</category>
      
      
      <comments>https://shuaixin.cc/Button-Library-Debounce/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>ESP32 小筆記</title>
      <link>https://shuaixin.cc/ESP32-WROOM/</link>
      <guid>https://shuaixin.cc/ESP32-WROOM/</guid>
      <pubDate>Wed, 05 Mar 2025 16:00:00 GMT</pubDate>
      
        
        
          
          
      <description></description>
          
        
      
      
      
      <content:encoded><![CDATA[<h3 id="電源供應">電源供應</h3><p>可以直接從 VIN 供電。</p><p>但如果你接上 USB，VIN 就變成 5V 的輸出。</p><h3 id="Touch（內建電容觸控）">Touch（內建電容觸控）</h3><p>Touch 1 通常沒有 lay 出來。（因為共用了 GPIO0，很難正常作動）</p><p>Touch 2 共用了 GPIO2 的內建 LED ，注意別一起用。</p><h3 id="ADC">ADC</h3><p>ADC2 因為 wifi 驅動用了這隻腳，所以跟wifi不能同時使用</p><h3 id="UART">UART</h3><p>通常只看得到 U0 跟 U2，因為 U1 沒有 lay 出來。</p><h3 id="I2C">I2C</h3><p>傳輸速度 I2C 比 UART 更快，但兩條線一條是數據、一條是時脈，所以只能是半雙工。相對的，UART 可以全雙工。</p><p>但 I2C 可以一對多。所以每個設備要有 I2C address。</p><h3 id="while-Serial">while(!Serial)</h3><p>若在 setup 裡面寫<code>while(!Serial);</code>，可以在你打開終端機之前，code 卡在這行等你。</p><h3 id="Seiral-available">Seiral.available()</h3><p>當終端機有內容被輸入（按下enter後），<code>Seiral.available()</code>就會回傳大於零的訊息，可以利用這點拿來檢查是否有輸入。</p><h3 id="硬體中斷">硬體中斷</h3><p>相較於 Arduino 只有兩個腳位有支援硬體中斷，ESP32 幾乎每隻腳都可以。</p><p>且，EPS 可以支援判斷 Low, High, Change, Falling, Rising，而 Arduino 沒有 High。</p>]]></content:encoded>
      
      
      <category domain="https://shuaixin.cc/categories/%E5%85%B6%E4%BB%96/">其他</category>
      
      
      <category domain="https://shuaixin.cc/tags/ESP32/">ESP32</category>
      
      <category domain="https://shuaixin.cc/tags/Arduino/">Arduino</category>
      
      
      <comments>https://shuaixin.cc/ESP32-WROOM/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>Linux 系統架設 MQTT 伺服器</title>
      <link>https://shuaixin.cc/Mosquitto-MQTT/</link>
      <guid>https://shuaixin.cc/Mosquitto-MQTT/</guid>
      <pubDate>Mon, 03 Mar 2025 16:00:00 GMT</pubDate>
      
        
        
          
          
      <description></description>
          
        
      
      
      
      <content:encoded><![CDATA[<p>本篇利用 Mosquitto 設置一個 MQTT 伺服器，伺服器的 OS 為 Ubuntu 24.04.1 LTS。</p><p>在開始之前，MQTT 預設使用的 Port 號是 1883，防火牆的傳出傳入規則務必要設定一下，記得打開。</p><h3 id="安裝-Mosquitto">安裝 Mosquitto</h3><p>此例為 Linux 環境，我們利用 apt 進行 Mosquitto 套件的安裝：</p><figure class="highlight cmd"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo apt install mosquitto mosquitto-clients -y</span><br></pre></td></tr></table></figure><p>其中 mosquitto 套件是主要的 Mosquitto 伺服器，而 mosquitto-clients 包含了指令工具如 <code>mosquitto_sub</code>, <code>mosquitto_pub</code>。</p><p>而指令開頭的 <code>sudo</code> 的意思是：</p><blockquote><p>Super Idol 的笑容，都沒你的甜。八月正午的陽光，都沒你耀眼。</p></blockquote><p>我開玩笑的，其實是 superuser do。</p><p>接著我們透過 configuration 設定一下我們 Mosquitto 的規則。我們在 <code>/etc/mosquitto/conf.d/</code> 中，加入一個設定檔：</p><figure class="highlight cmd"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo nano /etc/mosquitto/conf.d/default.conf</span><br></pre></td></tr></table></figure><p>nano 是 Linux 自帶的文件編輯程式，你可以用其他你會的方式來編輯這個 conf 檔。我們添加下列設定：</p><figure class="highlight txt"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">allow_anonymous true</span><br><span class="line">listener 1883 0.0.0.0</span><br></pre></td></tr></table></figure><p>這代表我接受任何匿名傳入資訊，只要你從 1883 這個 port 進來，來者不拒，方便我們前期快速測試。</p><p>設定好之後，我們重啟 mosquitto：</p><figure class="highlight cmd"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo systemctl restart mosquitto</span><br></pre></td></tr></table></figure><p>現在，我們想要讓這台伺服器接受傳入。我們輸入指令 <code>mosquitto_sub -h my_public_ip -t my_topic</code>。</p><p>其中，my_public_ip 填入這台伺服器的外網IP外置、my_topic 隨意填入你要訂閱的主題。</p><p>此時，這裡的 <code>mosquitto_sub</code> 代表我現在作為 subscriber，要訂閱所有關於 my_topic 的消息，以後有 publisher 發出 my_topic 的消息，我都會收到。</p><h3 id="收發消息">收發消息</h3><p>假設我伺服器的 IP 現在是 87.87.87.87，所以我輸入：</p><figure class="highlight cmd"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mosquitto_sub -h <span class="number">87</span>.<span class="number">87</span>.<span class="number">87</span>.<span class="number">87</span> -t beiqi</span><br></pre></td></tr></table></figure><p>我用另一台電腦輸入如下指令：</p><figure class="highlight cmd"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mosquitto_pub -h <span class="number">87</span>.<span class="number">87</span>.<span class="number">87</span>.<span class="number">87</span> -t beiqi -m &quot;呼叫波士頓，over！&quot;</span><br></pre></td></tr></table></figure><p>此時 server 應該就會收到「呼叫波士頓，over！」。</p><p>當然，請注意作為 publisher 的電腦也要允許傳出，如果你失敗了請查看一下是否是防火牆在搞。</p><h3 id="設定認證機制">設定認證機制</h3><p>現在，我不想收到一堆垃圾訊息，希望可以建立認證方式，讓擁有權限的人才能 publish 內容過來。那麼我們可以透過 <code>mosquitto_passwd -c &lt;password file&gt; &lt;username&gt;</code> 來創建帳號密碼。</p><p>好的此時我們輸入：</p><figure class="highlight cmd"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo mosquitto_passwd -c /etc/mosquitto/passwd user_87</span><br></pre></td></tr></table></figure><p>其中 <code>-c</code> 代表 create，因為這是我們第一次設置用戶跟密碼，這步驟會幫我們建立一個名為 passwd 的檔案（passwd可以自己隨意取名）。而 user_87 為用戶名。</p><p>執行後會請你輸入密碼，此例中，我們輸入 12345。</p><p>完成之後，我們要回頭修改前面的 <code>/etc/mosquitto/conf.d/default.conf</code>，改成：</p><figure class="highlight txt"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">allow_anonymous false</span><br><span class="line">password_file /etc/mosquitto/passwd</span><br><span class="line">listener 1883 0.0.0.0</span><br></pre></td></tr></table></figure><p>目前為止，標準的做法是這樣沒錯。但根據我的經驗，如果此時就重啟 Mosquitto，會報如下錯誤：</p><blockquote><p>Job for mosquitto.service failed because the control process exited with error code. See “systemctl status mosquitto.service” and “journalctl -xeu mosquitto.service” for details.</p></blockquote><p>問題其實是，我們建立出來的 passwd 的權限太高了，我們要調整一下：</p><figure class="highlight cmd"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo chmod <span class="number">644</span> /etc/mosquitto/passwd</span><br></pre></td></tr></table></figure><p>此處的 <code>chmod</code> 是 change mode 的意思，644 旨在把權限調低，這裡有點離題所以不做展開咯。</p><h3 id="收發帶認證的消息">收發帶認證的消息</h3><p>設定完賬號密碼後，我們的伺服器作為 subscriber 輸入：</p><figure class="highlight cmd"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mosquitto_sub -h <span class="number">87</span>.<span class="number">87</span>.<span class="number">87</span>.<span class="number">87</span> -t beiqi -u user_87 -P <span class="number">12345</span></span><br></pre></td></tr></table></figure><p>其中 <code>-u</code> 代表用戶名、<code>-P</code> 代表密碼。這裡都輸入剛剛設定好的內容。</p><p>而另一台電腦作為 publisher 則輸入：</p><figure class="highlight cmd"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mosquitto_pub -h <span class="number">87</span>.<span class="number">87</span>.<span class="number">87</span>.<span class="number">87</span> -t beiqi -u user_87 -P <span class="number">12345</span> -m &quot;還要打帳號密碼好麻煩！&quot;</span><br></pre></td></tr></table></figure><p>此時伺服器就會收到「還要打帳號密碼好麻煩！」的訊息咯！</p>]]></content:encoded>
      
      
      <category domain="https://shuaixin.cc/categories/%E5%85%B6%E4%BB%96/">其他</category>
      
      
      <category domain="https://shuaixin.cc/tags/MQTT/">MQTT</category>
      
      <category domain="https://shuaixin.cc/tags/Mosquitto/">Mosquitto</category>
      
      
      <comments>https://shuaixin.cc/Mosquitto-MQTT/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>OrCAD Capture 利用電晶體實作 Not Gate</title>
      <link>https://shuaixin.cc/OrCAD-BJT/</link>
      <guid>https://shuaixin.cc/OrCAD-BJT/</guid>
      <pubDate>Wed, 19 Feb 2025 16:00:00 GMT</pubDate>
      
        
        
          
          
      <description></description>
          
        
      
      
      
      <content:encoded><![CDATA[<p>平常我們都把邏輯閘當做最小單位在把玩，但邏輯閘內部是怎麼實踐的呢？我們用電晶體來實作一個反向器看看，走起！（基礎操作請見<a href="https://shuaixin.cc/OrCAD-Capture-Demo/">使用 OrCAD Capture 設計電路</a>）</p><p>本次的主角是這顆 Q2N2222，一顆 NPN 電晶體：</p><p><img src="/OrCAD-BJT/image-20250220103052107.png" alt="image-20250220103052107"></p><p>首先搜尋「Q2N2222」找到我們的電晶體：</p><p><img src="/OrCAD-BJT/BJT10.png" alt="BJT10"></p><p>組織一下電路：</p><p><img src="/OrCAD-BJT/BJT9.png" alt="BJT9"></p><p>我們搜尋「VPulse」來放置一個方波脈衝（簡單模擬一下數位訊號）：</p><p><img src="/OrCAD-BJT/BJT8.png" alt="BJT8"></p><p>方波脈衝信號的參數分別代表什麼？</p><ul><li>V1：基準電壓</li><li>V2：脈衝電壓</li><li>TD：Time Delay，就是發出第一個 V2 之前的等待時間。</li><li>TR：Time Rise，就是 V1 上升到 V2 之間的時間差，值越小越陡峭。記得一定要設定，為 0 的話會報錯。</li><li>TF：Time Fall，同理，就是 V1 回到 V2 之間的時間差，一樣記得要設定。</li><li>PW：Pulse Width，每個 V2 的持續時間。</li><li>PER：Period，一個 V1 加上一個 V2 的持續時間。</li></ul><p>理解之後，我們設置參數如下：</p><p><img src="/OrCAD-BJT/BJT7.png" alt="BJT7"></p><p>如此一來應該就看得懂了，這軟體真的也是很省字（汗顏）。</p><p>再來我們提供一個直流輸入源，設置為 3V：</p><p><img src="/OrCAD-BJT/BJT5.png" alt="BJT5"></p><p>根據我們的脈衝週期（100毫秒），我們跑模擬的參數設置如圖：</p><p><img src="/OrCAD-BJT/BJT11.png" alt="BJT11"></p><p>探棒分別設置在電晶體的基極（圖中綠色探棒）跟最後的輸出（圖中紅色探棒）：</p><p><img src="/OrCAD-BJT/BJT4.png" alt="BJT4"></p><p>跑下去可以看到：</p><p><img src="/OrCAD-BJT/BJT2.png" alt="BJT2"></p><p>其中綠色是我們的脈衝源，當脈衝發出時（相當於數位訊號的1），我們的紅色就不輸出（相當於數位訊號的0），因為此時電晶體導通，3V 的直流輸入源直接接地跑走了。反之，當脈衝停止，電晶體斷路，3V 的直流輸入源就跑向輸出。</p><p>如此一來，我們的綠色訊號就跟紅色訊號呈現反向關係，Not Gate 完工！</p><hr><p>同場加映（？），我們換一個正弦波當做基極的輸入：</p><p><img src="/OrCAD-BJT/BJT3.png" alt="BJT3"></p><p>結果如圖：</p><p><img src="/OrCAD-BJT/BJT1.png" alt="BJT1"></p>]]></content:encoded>
      
      
      <category domain="https://shuaixin.cc/categories/%E5%85%B6%E4%BB%96/">其他</category>
      
      
      <category domain="https://shuaixin.cc/tags/OrCAD/">OrCAD</category>
      
      <category domain="https://shuaixin.cc/tags/Capture/">Capture</category>
      
      
      <comments>https://shuaixin.cc/OrCAD-BJT/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>讀書筆記：《人生順利的簡單法則》</title>
      <link>https://shuaixin.cc/Lessons-to-Achieve-Great-Results/</link>
      <guid>https://shuaixin.cc/Lessons-to-Achieve-Great-Results/</guid>
      <pubDate>Fri, 07 Feb 2025 16:00:00 GMT</pubDate>
      
        
        
          
          
      <description></description>
          
        
      
      
      
      <content:encoded><![CDATA[<p><img src="/Lessons-to-Achieve-Great-Results/lessons.jpeg" alt="lessons"></p><h3 id="拖延、忙碌反而生產力高？">拖延、忙碌反而生產力高？</h3><p>美國芝加哥大學和中國上海交通大學的研究顯示：即使繁忙程度被迫超過可負荷范圍，人還是會因為繁忙而感到幸福。許多人都相信悠閒會使人幸福，但事實反而相反。</p><p>令人遺憾的是，我找不到這篇文獻的出處，書中也沒有附註（事實上，全書沒有半個註腳）。</p><p>那拖延呢？這裡引用的是史丹佛大學哲學系教授 John Perry 的招式：待辦事項裡如果有個最棘手的傢伙，那麼其他事項就會顯得誘人。我們利用這點，拖延大魔王，讓其他小兵顯得可愛，我們就會一直去執行那些簡單的任務。</p><p>總地來說，其實結論是：忙碌反而會幸福、拖延反而有效率，才對。（「拖延、忙碌反而生產力高？」是書中原本的章節名稱）</p><h3 id="姿勢的力量">姿勢的力量</h3><p>作者在「想提升效率，從改變姿勢開始」章節中引用了 Cuddy 著名的「高權力姿勢」（Power Pose）。其研究指出，採取象徵自信的姿勢，會使得睪固酮濃度上升、皮質醇的濃度下降。這意味著…… 更多的自信與較低的壓力。而這樣的順序，有悖於我們的直覺——難道不是先「感到」自信，才進而「表現」得自信嗎？</p><p>類似這樣先後順序的討論，濫觴可能是「臉部回饋假說」（Facial Feedback Hypothesis）——表情會反過來影響內在情緒。猜猜看最先提出這個想法的人是誰？達爾文！（出自 1872 年出版的《人類與動物的情感表達》，深遠的洞見啊達哥。）</p><p>還記得我們在 Gazzaniga《<a href="https://shuaixin.cc/%E8%AE%80%E6%9B%B8%E7%AD%86%E8%A8%98-%E6%88%91%E5%80%91%E7%9C%9F%E7%9A%84%E6%9C%89%E8%87%AA%E7%94%B1%E6%84%8F%E5%BF%97%E5%97%8E/">我們真的有自由意志嗎</a>》討論過的「情緒先行、感受其後」嗎？我們在意識無法感知到的魚腥味環境之下變得更加容易猜忌、我們在視網膜被快速閃過一張意識無法感知到的駭人照片之後變得緊張、我們不是因為遇見了喜歡的人感到開心而是因為開心所以認為自己喜歡這個人…… 「情緒」是個身心綜合狀態，而「感受」是我們的「左腦解釋器」讀取情緒以後，所描述出來的「解釋」。</p><p>所以我們可以這樣理解：「微笑」不只是個表情，它就是情緒本身；「高權力姿勢」不只是個動作，它也是情緒本身。而當左腦解釋器發現你在微笑，就會認為你很開心。此即「感受其後」。</p><h3 id="閒聊的力量">閒聊的力量</h3><p>在「閒聊的力量」章節中作者提到，工作上的「非正式交流」可以使人專注力更高，並且還能提升自己的「社會資本」，同事會容易給你更高的評價。</p><p>這題其實我們在《<a href="https://shuaixin.cc/The-Power-Of-Output/">最高學以致用法</a>》裡面就學過了，根據「單純曝光效應」（Mere Exposure Effect），我們會單純地因為熟悉某個事物就對它產生好感。所以只要多打招呼多閒聊，你自然而然會被喜歡。這也是為什麼競選廣告什麼文案都不用附也沒關係，反正就是要能被看到。這也是為什麼掛名贊助的產品只要掛名就好，反正能被看到就好。</p><h3 id="幹勁的有無只是一種幻想">幹勁的有無只是一種幻想</h3><p>作者提到，若從心理學的角度出發，幹勁不是一種會「失去」的「物品」。提不起勁，只是找不到具體的方法罷了。</p><p>接著端上了自我決定理論（SDT）的三個動力要素：自主性、關聯性、勝任感（書中的用詞是「熟練」，我猜是本作從英文翻譯成日文，再二度翻譯成中文所致）。</p><p>嘿，這三大動力要素我們在《<a href="https://shuaixin.cc/%E8%AE%80%E6%9B%B8%E7%AD%86%E8%A8%98-%E5%8F%AA%E5%B7%A5%E4%BD%9C%E4%B8%8D%E4%B8%8A%E7%8F%AD%E7%9A%84%E8%87%AA%E4%B8%BB%E4%BA%BA%E7%94%9F/">只工作不上班的自主人生</a>》討論過對吧，如果進行一項任務可以滿足這三個需求，那麼內在的動力就會容易自發地湧現。</p><h3 id="緊張反而帶來好表現">緊張反而帶來好表現</h3><p>容易緊張常常被我們視為是一種劣勢，或甚至是一種缺點。因為交感神經活躍帶來的戰與逃反應，主要是拿來…… 戰與逃，此時血液被大量地輸往骨骼肌，好方便我們可以揍人或是開溜。就演化的角度來看這十分合理，但二十一世紀的人類社會通常用不太到這方面的機制。相反地，激起我們戰與逃反應的可能會是在群眾面前發表談話、應一個重要的試。此時，最需要好好發揮用處的前額葉皮質反而得不到充分的資源（雖然腦部確實會增加血流量，但反正不是拿去供應負責高級思考的前額葉），於是搞砸了一切。</p><p>以上是我對於「緊張」的認識。但書中提到：</p><ul><li>壓力反應旺盛的運動選手通常競爭力較高</li><li>考前腎上腺素分泌較多的學生得分會較高</li><li>在和綁匪談判時，心跳逐漸加速的警察，比較不會誤射到人質</li><li>比較能夠「接納不安」（理解緊張焦慮也能是種助力）的人，唱歌比較不容易走音。</li></ul><p>挺有趣的，對於需要冷靜判斷的場景，居然也可能化緊張為正向助力。依舊可惜的是，作者提到的文字就跟我上面列舉的一樣精煉，沒有給出出處，難以進一步討論。</p><h3 id="Other-Good-Points">Other Good Points</h3><ul><li>尋求該如何達成目標的建議，而非是否該追求目標。</li><li>新年新希望不要聚焦在想要達成的「目標」，而是「原因」。</li><li>內在驅力比起外部報酬，品質更高。</li><li>將「嫉妒」的情緒透露給他人，會比較容易因此遇到好事。</li><li>「為了恢復注意力，滑個手機休息一下」跟「為了助眠，睡前喝個酒」都是看似合理但完全反效果的策略。</li><li>即使很忙時間不夠，一個小時內一樣只用45分鐘為單位進行工作，剩下的15分鐘要去做一些讓自己開心、豐富心靈的事。</li></ul><h3 id="敝人在下我的碎碎唸">敝人在下我的碎碎唸</h3><p>曾看過作者的《輕鬆駕馭意志力》，十分有料，故看到這本直接無腦下單。然而這本不太一樣。</p><p>不曉得為什麼這本沒有在美國出版，而是被翻譯成日文在日本出版。更有趣的是，中譯本甚至是從日文本翻譯過來的。經過了雙重翻譯後，總感覺用字遣詞有點不夠精確。</p><p>除此之外，這本的權威感也低了很多，不若《輕鬆駕馭意志力》那樣四處沿引研究、各個論述都有理論背書，這本給人的感覺是單純作者的人生經驗分享。不是不能接受經驗談，但就跟我的期望不太一樣就是了。</p>]]></content:encoded>
      
      
      <category domain="https://shuaixin.cc/categories/%E8%AE%80%E6%9B%B8%E7%AD%86%E8%A8%98/">讀書筆記</category>
      
      
      <category domain="https://shuaixin.cc/tags/3%E9%A1%86%E6%98%9F%E6%9B%B8%E7%B1%8D/">3顆星書籍</category>
      
      
      <comments>https://shuaixin.cc/Lessons-to-Achieve-Great-Results/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>將米家藍牙溫濕度計 2 刷成 Zigbee</title>
      <link>https://shuaixin.cc/Mi_Thermometer_Zigbee_LYWSD03MMC/</link>
      <guid>https://shuaixin.cc/Mi_Thermometer_Zigbee_LYWSD03MMC/</guid>
      <pubDate>Tue, 04 Feb 2025 16:00:00 GMT</pubDate>
      
        
        
          
          
      <description></description>
          
        
      
      
      
      <content:encoded><![CDATA[<p>本文將引導大家「免接線」將「米家藍牙溫濕度計 2」（型號：LYWSD03MMC）刷成 Zigbee，方便後續透過 Zigbee2MQTT 接入 Home Assistant。</p><p>小米官方在韌體更新到 2.1.1_0159 後（2024 後出廠的基本上都是這個版本號），資訊傳輸多了加密，讓 OTA 刷法一度失效了一兩年之久，如今重出江湖！</p><p>事不宜遲，開刷。</p><p><img src="/Mi_Thermometer_Zigbee_LYWSD03MMC/Mi.png" alt="Mi"></p><h3 id="設備先接入米家app">設備先接入米家app</h3><p>首先先按照小米官方指引，用常規的方式將你的溫度計設定妥當，接入米家。</p><p>此步驟為了後續可以得到溫度計的 ID、Token、Key。</p><h3 id="取得設備Token">取得設備Token</h3><p>你可以用任何你會的方法取得 ID、Token、Key。</p><p>如果你沒有頭緒，可以使用：<a href="https://github.com/PiotrMachowski/Xiaomi-cloud-tokens-extractor">https://github.com/PiotrMachowski/Xiaomi-cloud-tokens-extractor</a></p><p>以我為例，我用 mac 找到我米家帳號下面設備們的資訊：</p><p><img src="/Mi_Thermometer_Zigbee_LYWSD03MMC/token.png" alt="token"></p><h3 id="刷成過渡韌體">刷成過渡韌體</h3><p>使用 Telink Flasher for Mi Thermostat 網頁工具（<a href="https://pvvx.github.io/ATC_MiThermometer/TelinkMiFlasher.html">https://pvvx.github.io/ATC_MiThermometer/TelinkMiFlasher.html</a>），把韌體刷掉，脫離小米的掌控。</p><p>先 connect，找到藍牙設備並連上。</p><p>此時我們不按「Activate」，這個只適用舊的版本號。相對的，我們要使用「via login」。</p><p>為了 login，我們要填入剛剛得到的 token。</p><p>將 ID、Token、Key 填入後，我們點擊「via login」。</p><p>成功登入後，我們上傳 ATC_ota_40000.bin 這個檔案進去（檔案從：<a href="https://github.com/devbis/z03mmc/blob/master/assets/ATC_ota_40000.bin">https://github.com/devbis/z03mmc/blob/master/assets/ATC_ota_40000.bin</a>點擊下載後可得），點擊 flash 刷入。</p><p>成功後會自動斷開，不緊張。</p><h3 id="刷入-Zigbee-韌體">刷入 Zigbee 韌體</h3><p>接著我們使用 Telink Flasher to convert sensors to Zigbee 網頁工具（<a href="https://devbis.github.io/telink-zigbee/">https://devbis.github.io/telink-zigbee/</a>），準備刷入 Zigbee 韌體。</p><p>一樣先 connect，找到藍牙設備並連上。你的溫度計的名稱此時應該是 ATC 開頭。（但有時候名稱還是維持 LYWSD03MMC，我也不知道為什麼）</p><p>接著我們上傳 z03mmc.bin 這個檔案進去（檔案從：<a href="https://github.com/devbis/z03mmc/releases">https://github.com/devbis/z03mmc/releases</a>找到z03mmc.bin），點擊 flash 刷入。</p><p>成功！</p><h3 id="透過-Zigbee2MQTT-接入-HA">透過 Zigbee2MQTT 接入 HA</h3><p>再來就是走 Zigbee 接入我們的 HA 咯，方法請參考之前的 <a href="https://shuaixin.cc/HA-5-Zigbee/">智能家居 EP5：Zigbee 設備參戰</a>。</p><p>如果跟我一樣弄了超多顆的話，建議可以幫他們取個名字，不然真的會認錯人。我個人是幫他們在身上標記號碼作為區分。</p><p>附上我的全家福：</p><p><img src="/Mi_Thermometer_Zigbee_LYWSD03MMC/%E5%85%A8%E5%AE%B6%E7%A6%8F.png" alt="全家福"></p><p>如果一直搜尋不到，可以試著插拔一次電池，或短路 RESET 跟 GND 五秒以上。</p><p>以上！</p>]]></content:encoded>
      
      
      <category domain="https://shuaixin.cc/categories/%E6%99%BA%E8%83%BD%E5%AE%B6%E5%B1%85/">智能家居</category>
      
      
      <category domain="https://shuaixin.cc/tags/Home-Assistant/">Home Assistant</category>
      
      
      <comments>https://shuaixin.cc/Mi_Thermometer_Zigbee_LYWSD03MMC/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>OrCAD Capture 二極管半波整流</title>
      <link>https://shuaixin.cc/OrCAD-Diode/</link>
      <guid>https://shuaixin.cc/OrCAD-Diode/</guid>
      <pubDate>Sun, 02 Feb 2025 16:00:00 GMT</pubDate>
      
        
        
          
          
      <description></description>
          
        
      
      
      
      <content:encoded><![CDATA[<p>本篇我們來看看半導體的整流。基礎操作請見<a href="https://shuaixin.cc/OrCAD-Capture-Demo/">使用 OrCAD Capture 設計電路</a>。</p><p>我們這次選用 1N4148 作為我們的二極管：</p><p><img src="/OrCAD-Diode/shuai_02030939-41.png" alt="shuai_02030939-41"></p><p>繪製電路如下：</p><p><img src="/OrCAD-Diode/shuai_02030951-29.png" alt="shuai_02030951-29"></p><p>進行電路模擬：</p><p><img src="/OrCAD-Diode/shuai_02030948-06.png" alt="shuai_02030948-06"></p><p>電路模擬如下：</p><p><img src="/OrCAD-Diode/shuai_02030951-34.png" alt="shuai_02030951-34"></p><p>其中紅色為訊源，而綠色就是經過半波整流後的結果咯。</p>]]></content:encoded>
      
      
      <category domain="https://shuaixin.cc/categories/%E5%85%B6%E4%BB%96/">其他</category>
      
      
      <category domain="https://shuaixin.cc/tags/OrCAD/">OrCAD</category>
      
      <category domain="https://shuaixin.cc/tags/Capture/">Capture</category>
      
      
      <comments>https://shuaixin.cc/OrCAD-Diode/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>智能家居 EP10：將多盞燈組合成燈組</title>
      <link>https://shuaixin.cc/HA-10-Light-Group/</link>
      <guid>https://shuaixin.cc/HA-10-Light-Group/</guid>
      <pubDate>Wed, 22 Jan 2025 16:00:00 GMT</pubDate>
      
        
        
          
          
      <description></description>
          
        
      
      
      
      <content:encoded><![CDATA[<p>隨著我們的設備越來越多，會發現其實有些裝置總是同進同出，不太有分開來操作的需求，比如說同一組吊燈上的燈泡。</p><p>此時，我們就可以用到 Group 這個功能。</p><p>本來認為這應該是很常用，設定上應該要很簡單才對的功能，但 HA 的邏輯卻有點繞。</p><p>我們來一起操作看看，走起！</p><h3 id="新增群組">新增群組</h3><p>進入「設定 &gt; 裝置與服務 &gt; 助手」，點擊右下角「新增助手」，找到「群組」：</p><p><img src="/HA-10-Light-Group/Light_Group_0.png" alt="Light_Group_0"></p><p>群組藏在這個地方，實在是令人想不太到對吧 XD</p><p>我們選擇「燈光群組」，然後把你要組起來的燈都找進來：</p><p><img src="/HA-10-Light-Group/Light_Group_3.jpg" alt="Light_Group_3"></p><p>我的四顆燈就組隊完畢了：</p><p><img src="/HA-10-Light-Group/Light_Group_4.jpg" alt="Light_Group_4"></p><h3 id="操作群組">操作群組</h3><p>組隊完畢後，你會發現…… 誒？剛剛組起來的群組，找不到人！以我為例，我要在自動化裡面，設定按下按鈕就打開整組客廳左右燈，但找了很久都只能找到落單的實體，而非群組。</p><p>出乎意料地，我們要去「執行動作」：</p><p><img src="/HA-10-Light-Group/Light_Group_7.jpg" alt="Light_Group_7"></p><p>然後找到「燈光: 開關」（選項有點多，找不到就用搜尋的）：</p><p><img src="/HA-10-Light-Group/Light_Group_8.jpg" alt="Light_Group_8"></p><p>最後，我們才能在這個「動作」裡面找到我們設定好的燈光群組：</p><p><img src="/HA-10-Light-Group/Light_Group_9.jpg" alt="Light_Group_9"></p><p>如此我們就可以成功操控燈光群組咯 :)</p><p>所以我說，這邏輯確實很繞對吧？</p>]]></content:encoded>
      
      
      <category domain="https://shuaixin.cc/categories/%E6%99%BA%E8%83%BD%E5%AE%B6%E5%B1%85/">智能家居</category>
      
      
      <category domain="https://shuaixin.cc/tags/Home-Assistant/">Home Assistant</category>
      
      
      <comments>https://shuaixin.cc/HA-10-Light-Group/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>OrCAD Capture 透過 Parameters 討論變數</title>
      <link>https://shuaixin.cc/OrCAD-Capture-Para/</link>
      <guid>https://shuaixin.cc/OrCAD-Capture-Para/</guid>
      <pubDate>Mon, 20 Jan 2025 16:00:00 GMT</pubDate>
      
        
        
          
          
      <description></description>
          
        
      
      
      
      <content:encoded><![CDATA[<p>在<a href="https://shuaixin.cc/OrCAD-Capture-Demo/">使用 OrCAD Capture 設計電路</a>中我們已經學會如何繪製電路圖，並且使用 PSpice 模擬電路的運作情形。</p><p>今天我們要在同一個電路架構之下，設定一個參數作為變數，針對不同的輸入值繪製對應的圖形。</p><p>先來一個 RC 電路，訊號源是一個漂亮的方波脈衝：</p><p><img src="/OrCAD-Capture-Para/OrCAD_Para_8.png" alt="OrCAD_Para_8"></p><p>用 PSpice 模擬後發現，誠如我們對 RC 電路的認識，方波被 RC 電路磨去了棱角（方波的高頻諧波被我們過濾掉了）：</p><p><img src="/OrCAD-Capture-Para/OrCAD_Para_7.png" alt="OrCAD_Para_7"></p><p>那麼現在，我想知道不同的電容值，會對我的方波造成什麼不同的影響。</p><p>於是我們要來把圖中的電容（C1）設為變數。</p><p>我們從元件裡面搜尋「PARAM」找到「PARAM/SPECIAL」，放到圖中：</p><p><img src="/OrCAD-Capture-Para/OrCAD_Para_5.png" alt="OrCAD_Para_5"></p><p>接著雙擊 C1，將 C1 的電容值設定為 <code>{C}</code>。其中大括號裡面就是宣告一個變數。</p><p><img src="/OrCAD-Capture-Para/OrCAD_Para_4.png" alt="OrCAD_Para_4"></p><p>再來雙擊圖中的「<u>PARAMETERS:</u>」，會出現如下畫面，此時點擊「New Property」：</p><p><img src="/OrCAD-Capture-Para/OrCAD_Para_3.png" alt="OrCAD_Para_3"></p><p>此時添加我們剛剛設定的變數 C，電容值可以先隨便給一個：</p><p><img src="/OrCAD-Capture-Para/OrCAD_Para_2.png" alt="OrCAD_Para_2"></p><p>添加成功：</p><p><img src="/OrCAD-Capture-Para/OrCAD_Para_1.png" alt="OrCAD_Para_1"></p><p>回到我們的 PSpice 裡面，點擊左側「Edit Simulation Settings」，或是在電路圖上方選單的「PSpice &gt; Edit Simulation Profile」也可以。</p><p><img src="/OrCAD-Capture-Para/OrCAD_Para_17.png" alt="OrCAD_Para_17"></p><p>在此我們要勾選「Parametric Sweep」，並在「Global parameter」中將剛剛的 C 填入「Parameter name」。然後我們就可以來設定我們的 C 要怎麼玩。</p><p>此處我這樣設定就代表我想看 5u, 20u, 35u, 50u, 65u, 80u 電容值之下的六種情況：</p><p><img src="/OrCAD-Capture-Para/OrCAD_Para_13.png" alt="OrCAD_Para_13"></p><p>接著就可以點擊播放鍵，讓他跑跑看。而根據我們設定的六個參數，他會問你要看哪個，此處我們全選並按下 OK：<img src="/OrCAD-Capture-Para/OrCAD_Para_12.png" alt="OrCAD_Para_12"></p><p>噠啦：</p><p><img src="/OrCAD-Capture-Para/OrCAD_Para_11.png" alt="OrCAD_Para_11"></p><p>由圖可見，電容值越大，我的方波就被削得更圓潤。</p>]]></content:encoded>
      
      
      <category domain="https://shuaixin.cc/categories/%E5%85%B6%E4%BB%96/">其他</category>
      
      
      <category domain="https://shuaixin.cc/tags/OrCAD/">OrCAD</category>
      
      <category domain="https://shuaixin.cc/tags/Capture/">Capture</category>
      
      
      <comments>https://shuaixin.cc/OrCAD-Capture-Para/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>智能家居 EP9：利用DDNS、通訊埠轉發進行遠端控制</title>
      <link>https://shuaixin.cc/HA-X-Remote/</link>
      <guid>https://shuaixin.cc/HA-X-Remote/</guid>
      <pubDate>Sun, 19 Jan 2025 16:00:00 GMT</pubDate>
      
        
        
          
          
      <description></description>
          
        
      
      
      
      <content:encoded><![CDATA[<h2 id="出門在外也能控制-Home-Assistant-嗎？">出門在外也能控制 Home Assistant 嗎？</h2><p>出門在外也能控制 Home Assistant 嗎？必須得可以！這也是智能家居很重要的一環，舉凡人在外面控制燈具、瓦斯、門窗開關、透過攝影機查看家裡狀況、回家路上提前開冷氣、提前啟動電飯鍋開始煮飯…… 遠端控制是必不可少的功能。</p><p>此篇我們就來實作，走起！</p><h3 id="釐清家中的網路拓撲（怎麼互相連接的？如何上網的？）">釐清家中的網路拓撲（怎麼互相連接的？如何上網的？）</h3><p>以我為例，在此篇操作之前的拓撲為：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line">+———————+</span><br><span class="line">|中華電信|</span><br><span class="line">+———————+</span><br><span class="line">   |</span><br><span class="line">(PPPoE 撥號)</span><br><span class="line">   |</span><br><span class="line">   v</span><br><span class="line">+———————————————————————————————————————————+</span><br><span class="line">|小烏龜 (Modem + 路由器，內部網段：192.168.1.x)|</span><br><span class="line">+———————————————————————————————————————————+</span><br><span class="line">   |       </span><br><span class="line">(DHCP 分配 IP)</span><br><span class="line">   |     |</span><br><span class="line">   |     +---&gt; IPTV 1（客廳的MOD）</span><br><span class="line">   |     +---&gt; IPTV 2（房間的MOD）</span><br><span class="line">   v</span><br><span class="line">+—————————————————————————————————————+</span><br><span class="line">|MiWifi (路由器，內部網段：192.168.31.x)|</span><br><span class="line">+—————————————————————————————————————+</span><br><span class="line">   |</span><br><span class="line"> (DHCP 分配 IP )</span><br><span class="line">   |</span><br><span class="line">   +---&gt; 終端設備（手機、電腦等）</span><br><span class="line">   |</span><br><span class="line">   v</span><br><span class="line">+——————————————+</span><br><span class="line">|Home Assistant|</span><br><span class="line">+——————————————+</span><br></pre></td></tr></table></figure><p>建議各位一定要先稍微梳理一下家中的網路連接狀況，否則很容易跟我之前一樣犯很不必要的錯。（錯誤案例留在文末，供大家嘲笑並警惕）</p><p>此例中，我家裡同時有兩台路由器在搞路由，各自維護了兩個內網網段。所以假設我今天手機 wifi 連 MiWifi 來上網，實際上是小烏龜向中華電信取得了 <code>111.87.87.87</code> 這個外網 IP，然後 DHCP 分配給 MiWifi 一個內網 IP 例如 <code>192.168.1.69</code>，接著 MiWifi 再 DHCP 分配給手機一個內網 IP 如 <code>192.168.31.168</code> 來上網的。</p><p>一般家庭為了更好的 wifi 訊號額外買一台分享器是很常見的情形，而由於小烏龜本來就預設開著 DHCP，大家在安裝上很容易變得跟此例一樣。但如此一來，家裡變成了「雙重路由」，等等設定通訊埠轉發（Port Forwarding）會比較麻煩。</p><p>我這邊的解法是，MiWifi 改為 PPPoE 撥號直接跟中華電信額外再要一組 IP，各位不妨可以參考。不過如果你不介意，做兩層通訊埠轉發也是 ok 的。</p><h3 id="分享器直接撥號">分享器直接撥號</h3><p>反正中華電信可以同時給我們八組 IP（其實是不是挺大方的？還是因為台灣人口少所以沒差？），那我們就讓小烏龜拿一組（主要給MOD用）、MiWifi 也拿一組，各自對外。</p><p>你說你不知道你的 PPPoE 撥號帳號密碼？嗯跟我一樣，就打去中華電信問一下吧 XD</p><p><img src="/HA-X-Remote/pppoe.png" alt="pppoe"></p><p>順帶一提，帳號部分我本來輸入的是跟小烏龜一樣的 <a href="mailto:xxx@wifi.hinet.net">xxx@wifi.hinet.net</a> ，但連不上，於是嘗試了 <a href="mailto:xxx@hinet.net">xxx@hinet.net</a> 就意外成功了，各位可以嘗試。而 <a href="mailto:xxx@ip.hinet.net">xxx@ip.hinet.net</a> 應該是申請固定 IP 之後才會使用到的。</p><p>如此一來，我的拓撲就變成了：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line">+———————————————————————————+</span><br><span class="line">|          中華電信          |</span><br><span class="line">+———————————————————————————+</span><br><span class="line">   |           |</span><br><span class="line">(Modem)    (PPPoE 撥號)</span><br><span class="line">   |           |</span><br><span class="line">   |           v</span><br><span class="line">+———————————————————————————————————————————+</span><br><span class="line">|小烏龜 (Modem + 路由器，內部網段：192.168.1.x)|</span><br><span class="line">+———————————————————————————————————————————+</span><br><span class="line">   |       </span><br><span class="line">(PPPoE 撥號)</span><br><span class="line">   |     |</span><br><span class="line">   |     +---&gt; IPTV 1（客廳的MOD）</span><br><span class="line">   |     +---&gt; IPTV 2（房間的MOD）</span><br><span class="line">   v</span><br><span class="line">+—————————————————————————————————————+</span><br><span class="line">|MiWifi (路由器，內部網段：192.168.31.x)|</span><br><span class="line">+—————————————————————————————————————+</span><br><span class="line">   |</span><br><span class="line">(DHCP 分配 IP )</span><br><span class="line">   |</span><br><span class="line">   +---&gt; 終端設備（手機、電腦等）</span><br><span class="line">   |</span><br><span class="line">   v</span><br><span class="line">+——————————————+</span><br><span class="line">|Home Assistant|</span><br><span class="line">+——————————————+</span><br></pre></td></tr></table></figure><p>對於 MiWifi 來說，小烏龜此時就單純作為 Modem（數據機、調製解調器），而非上層路由器。對我們的 HA 來說，就是通向外網的障礙（？）少了一層，耶✌🏻</p><h3 id="固定HA的內網位置">固定HA的內網位置</h3><p>如果存粹交給 MiWifi 用 DHCP 來分配內網 IP 給 HA 的話，可能過一陣子位置就跑掉。所以我們來固定一下內網的 IP 位置：</p><p><img src="/HA-X-Remote/miwifi.png" alt="miwifi"></p><p>如此一來，HA 就會乖乖待在 <code>192.168.31.254</code> 了。</p><h3 id="設定通訊埠轉發（Port-Forwarding）">設定通訊埠轉發（Port Forwarding）</h3><p>此處注意「端口轉發」、「通訊埠轉發」、「Port Forwarding」指的是同一件事情，免得找不到設定入口。</p><p>此處可以先把外部的 80port（http 預設端口）轉到 IP為254（我們剛剛固定的位置）的 8123port（HA預設的端口）。簡單來說就是外部的 80 轉到內部的 8123。</p><p>而我們預先設好另一組外部 443 轉內部 8123，等等會用到。（443 是 https 預設端口）</p><p><img src="/HA-X-Remote/portfowarding.png" alt="portfowarding"></p><h3 id="設定DDNS-走-https">設定DDNS + 走 https</h3><p>而因為我這裡並沒有跟中華電信申請固定 IP，所以外網位置每隔一段時間會回收重發。那我從外網要怎麼追蹤 HA 目前最新的外網位置呢？</p><p>此處我們使用 DuckDNS 這個 DDNS 服務（動態DNS）。DuckDNS 透過附加元件安裝到 HA 裡面以後，會幫你偵測 HA 的外網位置，如果改變，就幫你記得，你只要用設定好的域名訪問就 ok 了，非常方便。</p><p>到 <a href="https://www.duckdns.org/">https://www.duckdns.org/</a> 註冊好，申請一組域名，取得 token。</p><p>接著從「設定 &gt; 附加元件 &gt;  附加元件商店」搜尋「Duck DNS」，安裝並開啟（記得設定成啟動時開啟）。進入 Duck DNS 裡面的設定（如下圖右側），填入你取得的域名與 token，在 Let’s Encrypt 欄位裡面填入：</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">accept_terms:</span> <span class="literal">true</span></span><br><span class="line"><span class="attr">algo:</span> <span class="string">secp384r1</span></span><br><span class="line"><span class="attr">certfile:</span> <span class="string">fullchain.pem</span></span><br><span class="line"><span class="attr">keyfile:</span> <span class="string">privkey.pem</span></span><br></pre></td></tr></table></figure><p>設定為 true 表示我們要透過 https 連線。</p><p>接著到 HA 的 <code>configuration.yaml</code> 加入設定（如下圖左側），如果你不知道怎麼編輯這個 file，請參考之前的<a href="https://shuaixin.cc/HA-7-File-Editor/">智能家居 EP7：File Editor</a>：</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">http:</span></span><br><span class="line">  <span class="attr">ssl_certificate:</span> <span class="string">/ssl/fullchain.pem</span></span><br><span class="line">  <span class="attr">ssl_key:</span> <span class="string">/ssl/privkey.pem</span></span><br></pre></td></tr></table></figure><p><img src="/HA-X-Remote/duck.png" alt="duck"></p><p>沒錯，DuckDNS 也幫我們集成了 Let’s Encrypt 的加密簽署服務了，揪甘心餒！</p><h3 id="HA開啟外部存取">HA開啟外部存取</h3><p>到「設定 &gt; 系統 &gt; 網路」將外部存取打開：</p><p><img src="/HA-X-Remote/remotegood.png" alt="remotegood"></p><h3 id="成功遠端訪問！">成功遠端訪問！</h3><p>至此，設定完畢 :)</p><hr><h2 id="錯誤示范">錯誤示范</h2><blockquote><p>當初網際網路知識還太嫩，失敗收場。將錯誤案例留下供大家參考，最後會解釋失敗原因。</p></blockquote><blockquote><p><s>此篇「遠端控制」失敗收場，目前未解，若有高手還請救救我QQ</s>（已解決！）</p></blockquote><p>為實現遠端連線，參考了以下三篇：</p><ul><li><a href="https://forum.automata.id/t/topic/153">Home Assistant 簡易遠端連線教學 - DuckDNS</a></li><li><a href="https://www.home-assistant.io/docs/configuration/remote/">Remote access</a></li><li><a href="https://medium.com/%E5%BD%BC%E5%BE%97%E6%BD%98%E7%9A%84-swift-ios-app-%E9%96%8B%E7%99%BC%E6%95%99%E5%AE%A4/home-assistant%E4%BD%BF%E7%94%A8duckdns%E8%87%AA%E5%AE%9A%E7%BE%A9%E5%AD%90%E5%9F%9F%E5%90%8D%E5%8F%8A%E6%8E%A1%E7%94%A8ssl-5713957d64b2">Home Assistant使用DuckDNS自定義子域名及採用SSL</a></li></ul><h3 id="路由器設定-Port-Forwarding">路由器設定 Port Forwarding</h3><p>路由器把 HA 伺服器的內網位置給固定住：</p><p><img src="/HA-X-Remote/miwifi.png" alt="miwifi"></p><p>然後設定好端口轉發：</p><p><img src="/HA-X-Remote/portfowarding.png" alt="portfowarding"></p><h3 id="HA-安裝-DuckDNS">HA 安裝 DuckDNS</h3><p>註冊好 DuckDNS，並在 HA 安裝完畢。</p><p>設定完畢：</p><p><img src="/HA-X-Remote/duckdns.png" alt="duckdns"></p><h3 id="HA-開啟外部存取">HA 開啟外部存取</h3><p>你看我這裡也開了：</p><p><img src="/HA-X-Remote/remotegood.png" alt="remotegood"></p><p>URL 也嘗試過各種方法了：</p><p><img src="/HA-X-Remote/url.png" alt="url"></p><p>我試過 https, http, 80, 443, 8123，在 port forwarding 的設定也給過 80, 443, 8123 諸如此類。但沒半個可以成功。</p><p>除了我訪問 <code>https://myurl.duckdns.org</code> 能連進我的中華電信小烏龜後台。</p><p>目前懷疑是小烏龜的設定問題，但進去檢查了一輪沒什麼特別發現。</p><h3 id="中華電信小烏龜後台">中華電信小烏龜後台</h3><p><img src="/HA-X-Remote/cht.png" alt="cht"></p><p>順帶一題，中華電信小烏龜後台進入的方式預設為：<code>https://192.168.1.1</code>。記得一定要走 https，否則不給進。</p><p>簡單設定可以選擇以 user 登入，帳號密碼皆為 <code>user</code>。</p><p>進階設定有一說是一定要實體乙太網路接電腦才能進去，但我這邊透過 wifi 進去也是可以的。帳號為 <code>cht</code>，密碼為小烏龜型號後四碼+小烏龜MAC後四碼，皆為小寫。以我為例即為 <code>25gqxxxx</code>。</p><h2 id="敗因解析">敗因解析</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">中華電信</span><br><span class="line">   |</span><br><span class="line">   | (PPPoE 撥號)</span><br><span class="line">   v</span><br><span class="line">小烏龜 (Modem + 路由器，內部網段：192.168.1.x)</span><br><span class="line">   |       |      </span><br><span class="line">   |       +---&gt; IPTV 1（客廳的MOD）</span><br><span class="line">   |       |</span><br><span class="line">   |       +---&gt; IPTV 2（房間的MOD）</span><br><span class="line">   |</span><br><span class="line">   | (DHCP 分配 IP)</span><br><span class="line">   v</span><br><span class="line">MiWifi (路由器，內部網段：192.168.31.x)</span><br><span class="line">   |</span><br><span class="line">   +---&gt; 終端設備（手機、電腦等）</span><br><span class="line">   |</span><br><span class="line">   +---&gt; Home Assistant</span><br></pre></td></tr></table></figure><p>當初的拓撲如上所示。</p><p>為什麼最後總是只能訪問到小烏龜後台呢？如今看來就很明顯了。</p><p>透過 DuckDNS 幫我們找到的外網的 IP 位置，是誰的位置呢？是小烏龜透過 PPPoE 撥號向中華電信借來的 IP，所以當然是直接連到小烏龜身上。</p><p>所以我們在 MiWifi 裡面用心地設置的 Port Forwarding 當然不會生效，因為壓根就沒有訪問請求進來過！</p><p>這題的解法有二：</p><ol><li>不改變上網方式的前提之下，可以設定兩層 Port Forwarding，小烏龜一層、MiWifi 再一層。</li><li>讓 MiWifi 也取得一組外網 IP。</li></ol><p>以我為例，反正中華電信允許多撥（可以同時撥八組），我 MiWifi 直接 PPPoE 要一組外網 IP，一切就迎刃而解了。</p>]]></content:encoded>
      
      
      <category domain="https://shuaixin.cc/categories/%E6%99%BA%E8%83%BD%E5%AE%B6%E5%B1%85/">智能家居</category>
      
      
      <category domain="https://shuaixin.cc/tags/Home-Assistant/">Home Assistant</category>
      
      
      <comments>https://shuaixin.cc/HA-X-Remote/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>智能家居 EP8：讓燈光隨著晝夜節律改變色溫</title>
      <link>https://shuaixin.cc/HA-8-Circadian-Light/</link>
      <guid>https://shuaixin.cc/HA-8-Circadian-Light/</guid>
      <pubDate>Wed, 15 Jan 2025 16:00:00 GMT</pubDate>
      
        
        
          
          
      <description></description>
          
        
      
      
      
      <content:encoded><![CDATA[<p>如何讓家裡的燈光色溫與自然的晝夜節律同步呢？此篇就來實作！</p><blockquote><p>本來這個需求我們選用了 <a href="https://github.com/claytonjn/hass-circadian_lighting?tab=readme-ov-file">hass-circadian_lighting</a> 的方案，但必須操作 configuration.yaml。</p><p>後來發現了 <a href="https://github.com/basnijholt/adaptive-lighting?tab=readme-ov-file#gear-configuration">adaptive-lighting</a>，可以純粹用圖形界面就搞定，那我們從善如流咯！</p></blockquote><h3 id="下載位置">下載位置</h3><p>首先在 HACS 中搜尋「Adaptive Lighting」，找到並點擊：</p><p><img src="/HA-8-Circadian-Light/Adaptive_Lighting_0008.jpg" alt="Adaptive_Lighting_0008"></p><p>就是這傢伙，咱們選擇下載：</p><p><img src="/HA-8-Circadian-Light/Adaptive_Lighting_0007.jpg" alt="Adaptive_Lighting_0007"></p><p>撰文當下版本為 v1.25.0：</p><p><img src="/HA-8-Circadian-Light/Adaptive_Lighting_0006.jpg" alt="Adaptive_Lighting_0006"></p><h3 id="安裝設定">安裝設定</h3><p>下載後，到「設定 &gt; 裝置與整合」中搜尋我們的 Adaptive Lighting：</p><p><img src="/HA-8-Circadian-Light/Adaptive_Lighting_0005.jpg" alt="Adaptive_Lighting_0005"></p><p>點擊設定：</p><p><img src="/HA-8-Circadian-Light/Adaptive_Lighting_0003.jpg" alt="Adaptive_Lighting_0003"></p><p>找到我們要套用的燈具：</p><p><img src="/HA-8-Circadian-Light/Adaptive_Lighting_0001.jpg" alt="Adaptive_Lighting_0001"></p><p>進行細節調整：</p><p><img src="/HA-8-Circadian-Light/Adaptive_Lighting_0000.jpg" alt="Adaptive_Lighting_0000"></p><p>此處我將最低色溫調整到 3000，因為再暖就真的太紅了，我個人不太適應。而最低亮度我也沒給太低，不然能見度真的快看不到了。</p><p>如此一來，我們的燈光就自動與目前的晝夜節律同步咯 :)</p>]]></content:encoded>
      
      
      <category domain="https://shuaixin.cc/categories/%E6%99%BA%E8%83%BD%E5%AE%B6%E5%B1%85/">智能家居</category>
      
      
      <category domain="https://shuaixin.cc/tags/Home-Assistant/">Home Assistant</category>
      
      
      <comments>https://shuaixin.cc/HA-8-Circadian-Light/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>智能家居 EP7：File Editor</title>
      <link>https://shuaixin.cc/HA-7-File-Editor/</link>
      <guid>https://shuaixin.cc/HA-7-File-Editor/</guid>
      <pubDate>Sun, 12 Jan 2025 16:00:00 GMT</pubDate>
      
        
        
          
          
      <description></description>
          
        
      
      
      
      <content:encoded><![CDATA[<p>來吧，接下來，我們要為未來的擴展性、可玩性做準備。</p><p>若我們將來要進行更多自定義操作，勢必會遇到要直接編輯 <code>configuration.yaml</code> 的情形。</p><p>故此篇，我們來安裝 File Editor。</p><blockquote><p>注意，如果你不是跟著我們系列文章一路設定過來的，使用了 container 或 core 的 HA 安裝方式的話，會因為沒有 Add-ons 而不適用此篇方法哦。</p></blockquote><h3 id="安裝-File-Editor">安裝 File Editor</h3><p>首先來到「設定 &gt; 附加元件」：</p><p><img src="/HA-7-File-Editor/HA-7-2.jpg" alt="HA-7-2"></p><p>此時可以看到目前為止安裝的附加元件。點擊「附加元件商店」：</p><p><img src="/HA-7-File-Editor/HA-7-1.jpg" alt="HA-7-1"></p><p>搜尋「File Editor」，可以看到有一個官方的 add-ons 就叫做「File editor」。我們點擊它：</p><p><img src="/HA-7-File-Editor/HA-7-3.jpg" alt="HA-7-3"></p><p>點擊後可以看到它的相關資訊，我們選擇「安裝」：</p><p><img src="/HA-7-File-Editor/HA-7-4.jpg" alt="HA-7-4"></p><p>安裝後，先別啟動。因為 File Editor 身為工具人，平常並沒有運行的必要，我們需要它的時候再找它出來就好。</p><p>所以這邊建議，啟動時不用開啟、當機時不用重啟、不用自動更新、側邊欄也不用顯示。都設定好以後，我們啟動來看看：</p><p><img src="/HA-7-File-Editor/HA-7-5.jpg" alt="HA-7-5"></p><p>選擇「開啟 Web UI」：</p><p><img src="/HA-7-File-Editor/HA-7-6.jpg" alt="HA-7-6"></p><p>此時畫面應該如下：</p><p><img src="/HA-7-File-Editor/HA-7-7.jpg" alt="HA-7-7"></p><p>我們點擊左上角的資料夾圖示，可以打開目錄：</p><p><img src="/HA-7-File-Editor/HA-7-8.jpg" alt="HA-7-8"></p><p>找到根目錄裡面的 <code>configuration.yaml</code>，打開它：</p><p><img src="/HA-7-File-Editor/HA-7-9.jpg" alt="HA-7-9"></p><p>成功！</p>]]></content:encoded>
      
      
      <category domain="https://shuaixin.cc/categories/%E6%99%BA%E8%83%BD%E5%AE%B6%E5%B1%85/">智能家居</category>
      
      
      <category domain="https://shuaixin.cc/tags/Home-Assistant/">Home Assistant</category>
      
      
      <comments>https://shuaixin.cc/HA-7-File-Editor/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>韓文小筆記之零：為什麼韓語發音那麼難？</title>
      <link>https://shuaixin.cc/Korean-X-IPA-Vowel/</link>
      <guid>https://shuaixin.cc/Korean-X-IPA-Vowel/</guid>
      <pubDate>Wed, 08 Jan 2025 16:00:00 GMT</pubDate>
      
        
        
          
          
      <description></description>
          
        
      
      
      
      <content:encoded><![CDATA[<p><img src="/Korean-X-IPA-Vowel/ipa_shuai-6384514.jpg" alt="ipa_shuai"></p><p>韓文學起來總覺得沒有日文那麼好上手，是我的錯覺嗎？也許不是哦。</p><p>本文提出一個華語使用者在學習韓語時，會遇到的「阻礙」——母音的異同。雖然很多學習資源都會稍微帶過這個課題，但不見誰引入第三方系統來討論它。</p><p>我們今天就用 IPA（International Phonetic Alphabet, 國際音標）來觀察一下，母音御五家（[a], [i], [u], [e], [o]）之中，韓語跟華語之間的對應關係是如何？又或者——其實無法對應？</p><h3 id="a">[a]</h3><p>好消息，「ㄚ」跟「아」的發音是一樣的，沒毛病。</p><p>有趣的是，日文「あ」在此處反而不太一樣，發音時的舌頭位置會往後退一點。然而這其實也不至於造成混淆，因為雖然嚴格來說「あ」會標成更準確的 /ä/，但由於在任何情況之下跟 /a/ 互換都不會影響意思表達（可視為我們之前討論過的<a href="https://shuaixin.cc/phoneme-allophone-variation/">自由變體</a>），平時用 /a/ 來描述也是 ok 的。</p><blockquote><p>結論：「ㄚ」跟「아」唸作 /a/；「あ」稍有不同唸作 /ä/。</p></blockquote><h3 id="i">[i]</h3><p>好消息第二彈，「ㄧ」、「い」、「이」的發音是一樣的，十分開心。</p><blockquote><p>結論：「ㄧ」、「い」、「이」都唸作 /i/。</p></blockquote><h3 id="u">[u]</h3><p>這裡就有幾個點要釐清了。</p><p>「ㄨ」跟「우」確實都是 /u/，但你知道日文的「う」其實是 /ɯ/ 嗎？從 IPA 的角度來看，這之間的差距還挺大的——唸 /u/ 的時候圓唇，唸 /ɯ/ 不圓唇。這就是我們唸日文聽起來不地道的核心問題之一。</p><p>重點來咯，你知道其實「으」不是唸「ㄜ」嗎？實際上，「으」跟「う」是一樣的 /ɯ/，而不是我們常常便宜行事而教的「ㄜ」。</p><blockquote><p>結論：「ㄨ」跟「우」唸作 /u/；「으」跟「う」唸作 /ɯ/。</p></blockquote><p>p.s. 「ㄜ」的 IPA 是 /ɤ/，半閉後不圓唇。</p><h3 id="e">[e]</h3><p>最熱門的問題來了：「애」跟「에」到底怎麼分？咱們就不要憑感覺亂描述了，IPA 作為一套標準可不是塑膠對吧？</p><p>「애」是半開前不圓唇的 /ɛ/，而「에」是嘴巴沒開那麼大的半閉前不圓唇 /e/。</p><p>那到底為什麼我們總是聽不出兩者的差別？理由倒也十分簡單，因為華語的「ㄝ」在 /ɛ/ 跟 /e/ 之間自由變體。白話來說，就是我們沒分那麼細，自然而然對這兩者的微妙差異不太敏感。（我們在<a href="https://shuaixin.cc/Why-3-Lie/">《為何三歲開始說謊》</a>認識過，全世界的語言加總起來有 800 多個音素，嬰兒全部都能分辨出來。但隨著成長（專化），敏銳度就會下降。）</p><p>而日文中的「え」跟我們是類似的情形。</p><blockquote><p>結論：「애」唸作 /ɛ/，「에」唸作 /e/；「ㄝ」跟「え」在 /ɛ/ 跟 /e/ 之間自由變體。</p></blockquote><h3 id="o">[o]</h3><p>「오」跟「어」又是一個課題。但其實這兩者的差別就比較大了，主要難點一樣在於華語裡面並沒有不圓唇的半開後元音，所以我們比較難用聽的去分辨。這個特別的傢伙就是唸作 /ʌ/ 的「어」。</p><p>而「오」就是我們比較熟悉的「ㄛ」了……嗎？</p><p>抱歉，還是要稍微注意一下，「ㄛ」跟「お」在 /ɔ/ 跟 /o/ 之間自由變體，概念跟剛剛是一樣的。但「오」比較嚴格地被歸在 /o/。</p><blockquote><p>結論：「어」唸作 /ʌ/，「오」唸作 /o/；而「ㄛ」跟「お」在 /ɔ/ 跟 /o/ 之間自由變體。</p></blockquote>]]></content:encoded>
      
      
      <category domain="https://shuaixin.cc/categories/%E8%AA%9E%E8%A8%80%E7%AD%86%E8%A8%98/">語言筆記</category>
      
      <category domain="https://shuaixin.cc/categories/%E8%AA%9E%E8%A8%80%E7%AD%86%E8%A8%98/%E9%9F%93%E6%96%87%E7%AD%86%E8%A8%98/">韓文筆記</category>
      
      
      <category domain="https://shuaixin.cc/tags/%E6%97%A5%E6%96%87/">日文</category>
      
      <category domain="https://shuaixin.cc/tags/%E9%9F%93%E6%96%87/">韓文</category>
      
      <category domain="https://shuaixin.cc/tags/IPA/">IPA</category>
      
      
      <comments>https://shuaixin.cc/Korean-X-IPA-Vowel/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>同位異音、互補分佈、自由變體</title>
      <link>https://shuaixin.cc/phoneme-allophone-variation/</link>
      <guid>https://shuaixin.cc/phoneme-allophone-variation/</guid>
      <pubDate>Wed, 01 Jan 2025 16:00:00 GMT</pubDate>
      
        
        
          
          
      <description></description>
          
        
      
      
      
      <content:encoded><![CDATA[<p><img src="/phoneme-allophone-variation/phoneme.jpg" alt="phoneme"></p><h3 id="互補分佈">互補分佈</h3><blockquote><p>在語言學中，當兩個語言成分（輔音、元音、詞素等）不能在同一個環境中出現，即處於互補分布（Complementary Distribution）。</p></blockquote><p>比如說，「stop」裡面的「t」我們唸不送氣的 /t/，而「tone」裡面的「t」我們唸送氣的 /tʰ/，而反過來並不成立。也就是說，在「stop」這個環境中，「t」不能唸作 /tʰ/；在「tone」這個環境中，「t」不能唸作 /t/。</p><p>於是我們可以說，在英語中， /t/ 跟 /tʰ/ 這兩個音位<strong>是</strong>互補分佈。</p><p>然而，同樣是  /t/ 跟 /tʰ/，在華語裡面並<strong>不是</strong>互補分佈。</p><p>舉例來說，顛（tian）跟天（tʰian）在同一個環境（-ian）之下都成立。</p><h3 id="同位異音">同位異音</h3><blockquote><p>同位異音（allophone）指的是一個音位可以表示多於一個音。</p></blockquote><p>白話來說，就是相同的音位（phoneme），但不同音素（phone）。</p><p>延續剛剛的例子，「stop」跟「tone」裡面的「t」是互補分佈，且發音相似，所以是同位異音。</p><h3 id="自由變體">自由變體</h3><blockquote><p>自由變異（free variation，又稱自由變體）在語音學上是指兩個（或多個）有差異的語音出現在相同的情境中、這兩者（或多者）可互相替代使用，而母語的使用者認為這二者（或多者）相同。</p></blockquote><p>白話來說，就是雖然唸出來不一樣，但完全不影響理解。</p><p>例如，華語中的「我」的發音其實一直被學者爭論究竟是 /o/（半閉後圓唇元音）或是 /ɔ/（半開後圓唇元音）。但其實，更有可能是兩種唸法同時存在。這種時候，無論你唸哪種，都不影響意思表達。此時這兩者就互為自由變體。</p>]]></content:encoded>
      
      
      <category domain="https://shuaixin.cc/categories/%E8%AA%9E%E8%A8%80%E7%AD%86%E8%A8%98/">語言筆記</category>
      
      
      <category domain="https://shuaixin.cc/tags/%E5%90%8C%E4%BD%8D%E7%95%B0%E9%9F%B3/">同位異音</category>
      
      
      <comments>https://shuaixin.cc/phoneme-allophone-variation/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>使用 OrCAD Capture 設計電路</title>
      <link>https://shuaixin.cc/OrCAD-Capture-Demo/</link>
      <guid>https://shuaixin.cc/OrCAD-Capture-Demo/</guid>
      <pubDate>Mon, 30 Dec 2024 16:00:00 GMT</pubDate>
      
        
        
          
          
      <description></description>
          
        
      
      
      
      <content:encoded><![CDATA[<p>OrCAD Capture 一打開，密密麻麻的選單，如何開始？</p><p>這裡簡單帶大家畫兩組電路來運作，給大家一點方向。走起！</p><h3 id="實際操作">實際操作</h3><p>打開 OrCAD Capture，起始頁面選擇 New Project。</p><p><img src="/OrCAD-Capture-Demo/OrCAD_Capture_Demo0018.jpg" alt="OrCAD_Capture_Demo0018"></p><p>選擇 PSpice Analog or Mixed A/D，這個我們才能模擬電路實際 run 起來的效果與監看各項參數。</p><p>取個名，選個存放位置，OK 走起。</p><p><img src="/OrCAD-Capture-Demo/OrCAD_Capture_Demo0017.jpg" alt="OrCAD_Capture_Demo0017"></p><p>此處我們開一個空白的來動手。</p><p><img src="/OrCAD-Capture-Demo/OrCAD_Capture_Demo0016.jpg" alt="OrCAD_Capture_Demo0016"></p><p>創建後就長這樣：<img src="/OrCAD-Capture-Demo/OrCAD_Capture_Demo0015.jpg" alt="OrCAD_Capture_Demo0015"></p><p>我們從右側的放置（place）選單裡面選擇部件（part），會發現我們還沒有部件可以使用。此處我們點擊 Add Library：</p><p><img src="/OrCAD-Capture-Demo/OrCAD_Capture_Demo0014.jpg" alt="OrCAD_Capture_Demo0014"></p><p>Cadence 套裝在安裝時應該都有附 Library 了，可以參考以下相對位置，選擇 pspice：</p><p><img src="/OrCAD-Capture-Demo/OrCAD_Capture_Demo0013.jpg" alt="OrCAD_Capture_Demo0013"></p><p>可以選你要的就好，但此處我們為了方便，直接全選後按開啟：</p><p><img src="/OrCAD-Capture-Demo/OrCAD_Capture_Demo0012.jpg" alt="OrCAD_Capture_Demo0012"></p><p>如此就導入進來了。</p><p>接著我們找電阻來用。搜尋 r 就可以找到 R/ANALOG。</p><p><img src="/OrCAD-Capture-Demo/OrCAD_Capture_Demo0011.jpg" alt="OrCAD_Capture_Demo0011"></p><p>點選 Place Part，或是直接 enter：</p><p><img src="/OrCAD-Capture-Demo/OrCAD_Capture_Demo0010.jpg" alt="OrCAD_Capture_Demo0010"></p><p>就可以在畫布上放置電阻，我們放四個。放完可以按 esc 結束放置：</p><p><img src="/OrCAD-Capture-Demo/OrCAD_Capture_Demo0009.jpg" alt="OrCAD_Capture_Demo0009"></p><p>用一樣的方法，我們找到 VDC/SOURCE 來放置電壓源，我們放兩個：</p><p><img src="/OrCAD-Capture-Demo/OrCAD_Capture_Demo0008.jpg" alt="OrCAD_Capture_Demo0008"></p><p>接著，我們從右側選單找到接地。或是直接按快捷鍵 G，我們放兩個：</p><p><img src="/OrCAD-Capture-Demo/OrCAD_Capture_Demo0007.jpg" alt="OrCAD_Capture_Demo0007"></p><p>接下來我們把這些東西用導線接成一組並聯、一組串聯。</p><p>拉導線（wire）的方法，一樣可以右邊選單找，或是快捷鍵 W。連接上很直覺，用滑鼠點擊就可以輕鬆佈線：</p><p><img src="/OrCAD-Capture-Demo/OrCAD_Capture_Demo0006.jpg" alt="OrCAD_Capture_Demo0006"></p><p>接著我們實際跑跑看這兩組電路。</p><p>上方導覽列選擇 PSpice 中的 New Simulation Profile：</p><p><img src="/OrCAD-Capture-Demo/OrCAD_Capture_Demo0005.jpg" alt="OrCAD_Capture_Demo0005"></p><p>選擇 PSpice A/D：</p><p><img src="/OrCAD-Capture-Demo/OrCAD_Capture_Demo0003.jpg" alt="OrCAD_Capture_Demo0003"></p><p>參數可以不要動（我這裡有動，但不影響），直接 OK。</p><p><img src="/OrCAD-Capture-Demo/OrCAD_Capture_Demo0002.jpg" alt="OrCAD_Capture_Demo0002"></p><p>接著點擊導覽列上的 Run PSpice，就會發現我們的 wire 上面模擬出了實際的電壓電流值：</p><p><img src="/OrCAD-Capture-Demo/OrCAD_Capture_Demo0001.jpg" alt="OrCAD_Capture_Demo0001"></p><p>但怎麼都是 0？哈，因為我們的電壓源是 0V，合情合理。我們雙擊我們的電壓源，隨便給它一些電壓，此處我給 50V。</p><p>設定完再 run 一次，就可以看到結果咯：</p><p><img src="/OrCAD-Capture-Demo/OrCAD_Capture_Demo0000.jpg" alt="OrCAD_Capture_Demo0000"></p>]]></content:encoded>
      
      
      <category domain="https://shuaixin.cc/categories/%E5%85%B6%E4%BB%96/">其他</category>
      
      
      <category domain="https://shuaixin.cc/tags/OrCAD/">OrCAD</category>
      
      <category domain="https://shuaixin.cc/tags/Capture/">Capture</category>
      
      
      <comments>https://shuaixin.cc/OrCAD-Capture-Demo/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>關於 C 與 Python</title>
      <link>https://shuaixin.cc/C-Python-note/</link>
      <guid>https://shuaixin.cc/C-Python-note/</guid>
      <pubDate>Sun, 29 Dec 2024 16:00:00 GMT</pubDate>
      
        
        
          
          
      <description></description>
          
        
      
      
      
      <content:encoded><![CDATA[<h3 id="弱型別-強型別">弱型別 &amp; 強型別</h3><p>Python 是弱型別語言，變數的型別在執行時才決定。所以你可以反覆橫跳也不會報錯：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">x = <span class="number">10</span>  <span class="comment"># x 是整數</span></span><br><span class="line">x = <span class="string">&quot;Hello&quot;</span>  <span class="comment"># 現在 x 變成字串，大丈夫，不會報錯</span></span><br></pre></td></tr></table></figure><p>但強型別的 C 就不行了，你要先宣告。</p><p>然而弱型別會讓效率差一點。你變數換來換去，表面上很方便，其實底層依舊有在幫你找新的地址來存東西，只是你不用自己操心。</p><p>為什麼 C 至今依舊不敗？就是因為底層的東西我們自己操心，自己操作，雖然難寫，但可控性更高。</p><h3 id="Python-自有一套記憶體管理術">Python 自有一套記憶體管理術</h3><p>比如說：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">&gt;&gt;&gt; a = &quot;hey&quot;</span><br><span class="line">&gt;&gt;&gt; id(a)</span><br><span class="line">4380090864</span><br><span class="line">&gt;&gt;&gt; a = 10</span><br><span class="line">&gt;&gt;&gt; id(a)</span><br><span class="line">4377258576</span><br><span class="line">&gt;&gt;&gt; b = a</span><br><span class="line">&gt;&gt;&gt; id(b)</span><br><span class="line">4377258576</span><br><span class="line">&gt;&gt;&gt; c = &quot;hey&quot;</span><br><span class="line">&gt;&gt;&gt; id(c)</span><br><span class="line">4380090800</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>當我賦值 b 跟 a 一樣，Python 就指向同一個位置，很省哦。但 C 語言中，就算兩個變數的賦值一樣，依然會分別存在兩個不同的位置。</p><p>好幾步之後，我們突然賦值 c （此處指上述程式碼中的變數c，不是C語言）為 “hey”，Python 還記得這個 “hey” 其實前面有人用過，反正記憶體也還沒把這個資料洗掉（還沒內存回收），你 c 就繼續用這個位置吧！可見，Python 自有一套記憶體管理術，而我們使用者也不用太操心這些環節。</p><h3 id="Character-String">Character &amp; String</h3><p>C 內建字元型別 char，如果你不引用外部的 library（例如 string.h），就只能用 char 來拼湊字串。這很合理，字串是人類在看的，咱 C 是面向硬體的。</p><p>Python 完全相反，沒有字元型別，但原生自帶字串型別 str。這很合理，Python 是面向咱人類的。</p><h3 id="Interpreter-Compiler">Interpreter &amp; Compiler</h3><p>Python 是用 interpreter 直譯的，一句一句執行。</p><p>C 是用 compiler 編譯成執行檔才能執行。</p><h3 id="遊戲引擎、嵌入式系統">遊戲引擎、嵌入式系統</h3><p>很多遊戲引擎都是用C語言開發的，虛幻引擎、Unity就是用C++。</p><p>據悉（C 的老師說的），後續的效能優化是對組合語言慢慢刪減調整。</p><p>嵌入式系統也常用C開發，同樣的理由，因為較為底層，所以輕量且高效。</p><h3 id="編譯順序">編譯順序</h3><p>C的編譯器是按照順序編譯的。</p><p>函數（function）要寫在主函數（main）的前面，若是反過來，編譯器會不知道你在調用什麼。</p><h3 id="printf-的處理順序">printf 的處理順序</h3><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> i = <span class="number">6</span>;</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">&quot;%d,%d,%d&quot;</span>, i, i++, i++);</span><br></pre></td></tr></table></figure><p>printf 位於 &lt;stdio.h&gt; 庫中。這段程式會輸出 <code>8,7,6</code> 。</p><p>p.s. <code>i++</code> 是「後置遞增」，表示在當前語句完成後，<code>i</code> 的值會增加；<code>++i</code> 則是「前置遞增」，先增加再賦值。</p><p>至於原因，跟編譯器的處理方式有關，三個變數從左到右被放到 stack 裡面，所以最後出來的順序是反過來。如果遇到 i++ 就先賦值了，而如果遇到 ++i 則運算完後把指標指向目前的 i。</p><p>然而這句包含未定義的行為，很危險，我們應該避免同一句裡面對同一個參數做多次修改。我們如果改成這樣：</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> i = <span class="number">6</span>;</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">&quot;%d,&quot;</span>, i);</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">&quot;%d,&quot;</span>, i++);</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">&quot;%d&quot;</span>, i++);</span><br></pre></td></tr></table></figure><p>如此就會輸出 <code>6,6,7</code>。</p><p>但如果：</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> i = <span class="number">6</span>;</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">&quot;%d,%d,%d&quot;</span>, i, ++i, ++i);</span><br></pre></td></tr></table></figure><p>你猜猜看會輸出什麼？輸出了 <code>8,8,8</code>，我暈。</p><h3 id="算數運算子">算數運算子</h3><p>C 跟 Python 裡面都有基本的 <code>a+b, a-b, a*b, a/b, a%b</code>，但其中 <code>a/b</code> 裡面 C 只給整數商，Python 會直接浮點送你小數點。</p><p>那 Python 要怎麼只拿整數商？必須寫作 <code>a//b</code> 才行。</p><p>另外 <code>a**b</code> 的指數運算 Python 有但 C 沒有。</p><h3 id="算數賦值運算子">算數賦值運算子</h3><p>a = a + 5中的「+」就是算術運算子，「=」就是賦值運算子。</p><p>來咯，C++ 跟 Python 裡面都有這兩者的合體——「算數賦值運算子」。</p><p>剛剛的 <code>a = a + 5</code> 用算數指定運算子簡化成 <code>a += 5</code>。總之就是，先進行運算，接著直接賦值成運算後的結果。</p><h3 id="return-0">return 0</h3><p>C++裡面常看到return 0：</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> <span class="title function_">main</span><span class="params">()</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>函數執行完一定要返回一個0嗎？嗯，收到0代表這個函數執行完畢。</p><p>而且其實就算你忘了 return 0，現在編譯器也會自己幫你 return 0。</p><h3 id="布林函數">布林函數</h3><p>C 沒有原生的布林函數，也就是他不認識 true 跟 false。但可以這樣玩：</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span>(<span class="number">0.1</span>)</span><br><span class="line">&#123;</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">&quot;不為0就為真&quot;</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>會 print 出來。</p><h3 id="三元運算子-ternary-operator">三元運算子 (ternary operator)</h3><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">printf</span>(<span class="string">&quot;%d&quot;</span>,(<span class="number">0</span>)?<span class="number">1</span>:<span class="number">2</span>);</span><br></pre></td></tr></table></figure><p>這裡因為括弧內為假，所以最後輸出「2」。</p><p>設條件居然還能不寫 if！C 真的很喜歡簡潔，但同時閱讀起來很不直觀。</p><p>喔其實 python 也有三元運算：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">print</span>(<span class="string">&quot;true&quot;</span> <span class="keyword">if</span> <span class="number">1</span> <span class="keyword">else</span> <span class="string">&quot;false&quot;</span>)</span><br></pre></td></tr></table></figure><h3 id="邏輯運算子">邏輯運算子</h3><p>Python 很貼心直接用自然語言的 and, or, not，而 C 分別是  <code>&amp;&amp;</code>, <code>||</code>, <code>!</code>。</p><h3 id="位元運算子">位元運算子</h3><p>C 底層到什麼程度呢？可以對位元進行操作。</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">printf</span>(<span class="string">&quot;%d&quot;</span>,<span class="number">13</span>&amp;<span class="number">7</span>);</span><br></pre></td></tr></table></figure><p>最後會得到「5」，因為我們對 13 跟 7 進行二進位的 AND 操作。</p><p>其他的還有 <code>|</code> for OR, <code>~</code> for not, <code>^</code> for XOR。</p><p>另外還能 <code>&lt;&lt;n</code> 就是左移位數（低位補零），其實就是乘以 2^n。反之就是 <code>&lt;&lt;n</code>。</p><p>Python 當然就沒有這些玩法了。</p><h3 id="Slicing">Slicing</h3><p>Python 獨有的 Slicing：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">b = <span class="string">&quot;Python rules!&quot;</span></span><br><span class="line"><span class="built_in">print</span>(b[::<span class="number">1</span>])  <span class="comment">#輸出 Python rules!</span></span><br><span class="line"><span class="built_in">print</span>(b[::-<span class="number">1</span>]) <span class="comment">#輸出 !selur nohtyP</span></span><br></pre></td></tr></table></figure><p>其中語法為 <code>sequence[start:stop:step​​]</code>。如果頭尾省略不寫的話，如果 step 為正，那就是開頭當做 start；若 step 為負，結尾當做 start。（如果 step 不寫的話，默認是 1）</p><p>居然在同一個語法自帶 if 判斷？好吧。</p><h3 id="物件導向-Object-Oriented">物件導向 Object-Oriented</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">b = <span class="string">&quot;Python&quot;</span></span><br><span class="line"><span class="built_in">print</span>(<span class="built_in">len</span>(b))  <span class="comment">#輸出 6</span></span><br><span class="line"><span class="built_in">print</span>(b.upper())   <span class="comment">#輸出 PYTHON</span></span><br></pre></td></tr></table></figure><p>作為物件導向的語言，在你創建了 <code>b=&quot;Python&quot;</code> 之後，Python 就自己幫你維護了關於 b 這個物件的各種資訊跟方法。</p><p>例如 <code>len(b)</code> 是 b 這個 string 的長度。你有自己寫程式去進行判斷嗎？沒有，但這件事 Python 幫你維護好了。</p><p>例如 <code>b.upper()</code> 就是一個方法，只要你是 string，都可以調用這個方法來將字串裡面的字都轉成大寫。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">print</span>(<span class="string">&quot;XD&quot;</span>*<span class="number">10</span>) <span class="comment">#輸出 XDXDXDXDXDXDXDXDXDXD</span></span><br></pre></td></tr></table></figure><p>你看連 string 的乘法都可以。</p><h3 id="容器們：Tuple-List-Dictionary-Set">容器們：Tuple, List, Dictionary, Set</h3><p>這些資料結構只有 Python 有。</p><table><thead><tr><th>特性</th><th><code>tuple</code></th><th><code>list</code></th></tr></thead><tbody><tr><td>可變性</td><td>不可變</td><td>可變</td></tr><tr><td>語法</td><td>小括號 <code>()</code></td><td>方括號 <code>[]</code></td></tr><tr><td>方法數量</td><td>僅有 <code>count</code> 和 <code>index</code></td><td>多數據操作方法（如 <code>append</code>）</td></tr><tr><td>性能</td><td>更高效（因為不可變性）</td><td>相對低效</td></tr><tr><td>使用場景</td><td>用於靜態數據</td><td>用於動態數據</td></tr></tbody></table><p>注意 tuple 如果只有一個元素時，必須加逗號：<code>single_element_tuple = (1,)</code></p><h3 id="解包-Unpacking">解包 Unpacking</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&gt;&gt;&gt; </span>tu = ((<span class="string">&#x27;1&#x27;</span>,<span class="string">&#x27;a&#x27;</span>),(<span class="string">&#x27;2&#x27;</span>,<span class="string">&#x27;b&#x27;</span>),(<span class="string">&#x27;3&#x27;</span>,<span class="string">&#x27;c&#x27;</span>))</span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span><span class="keyword">for</span> a,b <span class="keyword">in</span> tu:</span><br><span class="line"><span class="meta">... </span>  <span class="built_in">print</span>(a+<span class="string">&#x27;-&gt;&#x27;</span>+b)</span><br><span class="line"><span class="meta">... </span></span><br><span class="line"><span class="comment">#輸出</span></span><br><span class="line"><span class="comment">#1-&gt;a</span></span><br><span class="line"><span class="comment">#2-&gt;b</span></span><br><span class="line"><span class="comment">#3-&gt;c</span></span><br></pre></td></tr></table></figure><p>只要結構上大家能一一對應，通常 python 都能幫你兜在一起。</p><h3 id="f-string">f-string</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&gt;&gt;&gt; </span>name=<span class="string">&quot;Shuai&quot;</span></span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span>face=<span class="string">&quot;handsome&quot;</span></span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span><span class="built_in">print</span>(<span class="string">f&quot;Hi, my name is <span class="subst">&#123;name&#125;</span>. I&#x27;m very <span class="subst">&#123;face&#125;</span>, as you can see.&quot;</span>)</span><br><span class="line"><span class="comment">#輸出 Hi, my name is Shuai. I&#x27;m very handsome, as you can see.</span></span><br></pre></td></tr></table></figure><p>很方便餒！ 順帶一提，此例中的句子都是真人真事。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&gt;&gt;&gt; </span>pi=<span class="number">3.1415926</span></span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span><span class="built_in">print</span>(<span class="string">f&quot;pi= <span class="subst">&#123;pi:<span class="number">.2</span>f&#125;</span>&quot;</span>)</span><br><span class="line"><span class="comment">#輸出 pi= 3.14</span></span><br></pre></td></tr></table></figure><p>當然啦，指定格式也是可以的。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&gt;&gt;&gt; </span><span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">5</span>):</span><br><span class="line"><span class="meta">... </span>    <span class="built_in">print</span>(<span class="string">f&quot;<span class="subst">&#123;i&#125;</span>&quot;</span>, end=<span class="string">&quot; &quot;</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment">#輸出 0 1 2 3 4</span></span><br></pre></td></tr></table></figure><p>python 預設的 print 會幫你每次都換行（也就是 \n），怎麼自定義？用 f-string 可以指定 print 的結尾是什麼！</p><h3 id="偷偷幫你換行">偷偷幫你換行</h3><p>C 裡面你通常要自己透過 <code>\n</code> 來換行，不然大家就擠在同一行。</p><p>Python 不出意外地（？）很自動就幫你換行了，十分方便。但如果你今天不想換行的話，要特別跟他說一下，例如：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&gt;&gt;&gt; </span><span class="built_in">print</span>(<span class="string">&#x27;hi&#x27;</span>); <span class="built_in">print</span>(<span class="string">&quot;hello&quot;</span>)</span><br><span class="line">hi</span><br><span class="line">hello</span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span><span class="built_in">print</span>(<span class="string">&#x27;hi&#x27;</span>, end=<span class="string">&quot;不換行!&quot;</span>); <span class="built_in">print</span>(<span class="string">&quot;hello&quot;</span>)</span><br><span class="line">hi不換行!hello</span><br></pre></td></tr></table></figure><h3 id="字元轉整數（char-to-int）">字元轉整數（char to int）</h3><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> a = <span class="string">&#x27;9&#x27;</span>-<span class="string">&#x27;0&#x27;</span>;</span><br></pre></td></tr></table></figure><p>這行是啥？其實就是 a=9，酷吧！不會報錯哦。</p><h3 id="elif">elif</h3><p>大部分程式語言跟 C 一樣用 <code>else if</code> 作為條件判斷的語句。</p><p>就 python 跟大家不一樣用的是 <code>elif</code>。</p><h3 id="檢查是否完整執行-loop">檢查是否完整執行 loop</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&gt;&gt;&gt; </span><span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">10</span>):</span><br><span class="line"><span class="meta">... </span>  <span class="built_in">print</span>(<span class="string">f&quot;<span class="subst">&#123;i&#125;</span>&quot;</span>, end=<span class="string">&quot; &quot;</span>)</span><br><span class="line"><span class="meta">... </span><span class="keyword">else</span>:</span><br><span class="line"><span class="meta">... </span>  <span class="built_in">print</span>(<span class="string">&quot;It&#x27;s not broke, good!&quot;</span>)</span><br><span class="line"><span class="meta">... </span></span><br><span class="line"><span class="comment">#輸出 0 1 2 3 4 5 6 7 8 9 It&#x27;s not broke, good!</span></span><br></pre></td></tr></table></figure><p>python 還拿了 <code>else</code> 來判斷 loop 是否有被 <code>break</code>。</p><p>C 沒有類似的原生設計。</p><h3 id="函數註解">函數註解</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&gt;&gt;&gt; </span><span class="keyword">def</span> <span class="title function_">hello</span>():</span><br><span class="line"><span class="meta">... </span>  <span class="string">&quot;&quot;&quot;</span></span><br><span class="line"><span class="string"><span class="meta">... </span>  This is a function which says hello to you!</span></span><br><span class="line"><span class="string"><span class="meta">... </span>  &quot;&quot;&quot;</span></span><br><span class="line"><span class="meta">... </span>  <span class="built_in">print</span>(<span class="string">&quot;hello!&quot;</span>)</span><br><span class="line"><span class="meta">... </span></span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span>hello()</span><br><span class="line">hello!</span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span><span class="built_in">print</span>(hello.__doc__)</span><br><span class="line"></span><br><span class="line">  This <span class="keyword">is</span> a function which says hello to you!</span><br><span class="line">  </span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span><span class="built_in">help</span>(hello)</span><br><span class="line"><span class="comment">#他會打開同上的 doc</span></span><br></pre></td></tr></table></figure><p>C 有這種事嗎？沒有。</p><h3 id="函數內使用全域變數">函數內使用全域變數</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&gt;&gt;&gt; </span><span class="keyword">def</span> <span class="title function_">h1</span>():</span><br><span class="line"><span class="meta">... </span>  <span class="keyword">global</span> v</span><br><span class="line"><span class="meta">... </span>  v+=<span class="number">5</span></span><br><span class="line"><span class="meta">... </span>  <span class="keyword">return</span> v</span><br><span class="line"><span class="meta">... </span></span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span>v = <span class="number">1</span></span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span><span class="built_in">print</span>(h1())</span><br><span class="line"><span class="number">6</span></span><br></pre></td></tr></table></figure><p>Python 的函數內需要特別宣告 global 以後，才可以修改全域變數。（比較安全）</p><p>C 不用問，直接拿來用。（比較危險）</p><h3 id="串列生成式">串列生成式</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&gt;&gt;&gt; </span>checkthis = [(i,j) <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">5</span>) <span class="keyword">if</span> i%<span class="number">2</span> == <span class="number">0</span> <span class="keyword">for</span> j <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">5</span>) <span class="keyword">if</span> j%<span class="number">2</span> ==<span class="number">1</span>]</span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span><span class="built_in">print</span>(checkthis)</span><br><span class="line">[(<span class="number">0</span>, <span class="number">1</span>), (<span class="number">0</span>, <span class="number">3</span>), (<span class="number">2</span>, <span class="number">1</span>), (<span class="number">2</span>, <span class="number">3</span>), (<span class="number">4</span>, <span class="number">1</span>), (<span class="number">4</span>, <span class="number">3</span>)]</span><br></pre></td></tr></table></figure><p>這個 list 裡面直接包含了兩層 for+if。</p><h3 id="Python-有私有變數嗎？">Python 有私有變數嗎？</h3><p>形式上，有。</p><p>但其實透過 <code>_Class__private</code> 的方法，一樣可以操作這個變數。</p><p>為何 Python 不好好保護私有變數呢？因為 Python 的設計哲學說：“We are all consenting adults here.”，我們都是成年人了，你知道自己在做什麼就好。</p>]]></content:encoded>
      
      
      <category domain="https://shuaixin.cc/categories/%E5%85%B6%E4%BB%96/">其他</category>
      
      
      <category domain="https://shuaixin.cc/tags/C/">C++</category>
      
      <category domain="https://shuaixin.cc/tags/Python/">Python</category>
      
      
      <comments>https://shuaixin.cc/C-Python-note/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>透過 AIDA64 將 AX206 作為 Windows 的監控副屏</title>
      <link>https://shuaixin.cc/AX206-AIDA64/</link>
      <guid>https://shuaixin.cc/AX206-AIDA64/</guid>
      <pubDate>Wed, 25 Dec 2024 16:00:00 GMT</pubDate>
      
        
        
          
          
      <description></description>
          
        
      
      
      
      <content:encoded><![CDATA[<h2 id="監控副屏方案比較">監控副屏方案比較</h2><h3 id="雙螢幕">雙螢幕</h3><p>直觀來說，我們隨便拿另一顆螢幕來當做副屏不就好了嗎？很遺憾的，如此一來會有幾點問題：</p><ul><li>如果你沒有內顯（像我就是 13400F），副屏就會佔用 GPU 的資源。</li><li>就算你有內顯，因為副屏被作業系統視為顯示器，你的滑鼠會跑進去、你開的程式也有機會穿透過去。</li></ul><h3 id="舊手機">舊手機</h3><p>要避開上述問題，其實舊手機就是個好選擇，完全不佔用圖形處理資源，透過 AIDA64，用內網開個瀏覽器就可以監控。</p><p>但依舊有不盡理想之處：</p><ul><li>無法跟電腦同步作動。也就是沒辦法開機點亮、關機息屏，每次都要操作手機。</li><li>手機要一直插著電，閒暇時就是待機空轉。除非你願意每次手動開關機，那就更麻煩了。</li></ul><h3 id="圖靈智顯">圖靈智顯</h3><p>要避開上述所有問題，其實你可以……花錢辦事。</p><p>圖靈智顯就有專門在做副屏，屏幕裡面用他們自家的韌體，設定畫面也用他們自家的軟體，直接買他們的全套服務，免煩惱一步解決。</p><p>但問題就是：</p><ul><li>貴一些。</li></ul><p>雖然你直接淘寶的話，3.5 吋的副屏也就 500NTD 上下就能解決啦。但我自己能處理的事，當然要自己來咯。</p><h3 id="AX206-顯示屏">AX206 顯示屏</h3><p><img src="/AX206-AIDA64/ax206_1.png" alt="ax206_1"></p><p>從淘寶買這種可以被 AIDA64 支持的規格，一塊不到 300NTD。可以透過關鍵字 AX206 來找到這類產品。</p><p>本次就來分享怎麼點亮這塊螢幕並作為電腦副屏。</p><h2 id="使用方法">使用方法</h2><p>AX206 拿到後可以試著連連看，理論上是會亮，查看系統的裝置設定可以看到 USB Display。</p><p>實際到 AIDA64 裡面看看。找到偏好設定，選擇側邊欄的 LCD，接著選擇 AX206。</p><p>會發現裡面提示「建議對 AX206 裝置使用 libusb 驅動程式」。</p><p><img src="/AX206-AIDA64/AX206_4.png" alt="AX206_4"></p><p>然而 AIDA64 提供的檔案並沒辦法成功驅動，所以我們此處使用 Zadig 來安裝驅動。</p><p>安裝 Zadig 後執行，找到我們的 USB Display，選擇「libusb-win32」作為驅動。</p><p><img src="/AX206-AIDA64/AX206_2.png" alt="AX206_2"></p><p>安裝後，重啟電腦。</p><p>重啟後，再次打開 AIDA64 可以發現一切準備就緒。</p><p><img src="/AX206-AIDA64/AX206_3.png" alt="AX206_3"></p><p>什麼都不設定直接套用後，此時 AX206 應該就會顯示預設畫面了：</p><p><img src="/AX206-AIDA64/AX206_5.jpg" alt="AX206_5"></p><p>接著就可以進入「LCD 項目」自己設計畫面咯 :)</p>]]></content:encoded>
      
      
      <category domain="https://shuaixin.cc/categories/%E5%85%B6%E4%BB%96/">其他</category>
      
      
      <category domain="https://shuaixin.cc/tags/AX206/">AX206</category>
      
      <category domain="https://shuaixin.cc/tags/AIDA64/">AIDA64</category>
      
      
      <comments>https://shuaixin.cc/AX206-AIDA64/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>使用 Ventoy 取代 Rufus</title>
      <link>https://shuaixin.cc/rufus-vs-ventoy/</link>
      <guid>https://shuaixin.cc/rufus-vs-ventoy/</guid>
      <pubDate>Tue, 24 Dec 2024 16:00:00 GMT</pubDate>
      
        
        
          
          
      <description></description>
          
        
      
      
      
      <content:encoded><![CDATA[<h3 id="Rufus-不好嗎？">Rufus 不好嗎？</h3><p>自己灌過系統的都知道，用 Rufus 製作開機隨身碟雖然不麻煩，但同一時間、同一支隨身碟將無法挪作他用。假設你要用 Rufus 做一個 Ubuntu 開機碟，即使你的隨身碟有 1TB 的容量好了，雖然 Ubuntu 的 iso 才 5GB，剩下的空間一樣只能閒在那邊，看得到用不到。</p><p>本來以為這就是灌系統的必要之痛，要嘛特別養一支開機隨身碟，要嘛每次灌系統都要挑一支無辜的隨身碟出來格式化一次——直到我遇到了 Ventoy。</p><h3 id="Ventoy-太神了">Ventoy 太神了</h3><p>如果使用 Ventoy，只要你隨身碟容量允許，你要在裡面放多少個 iso 都可以。所以舉例來說，我能做一支可以灌 Win7, Win8, Win10, Win11, Ubuntu, CentOS, Debian 的超級開機隨身碟，想灌什麼皆是信手拈來。</p><p>更方便的是，因為只需要放 iso 檔案在隨身碟裡面，我剩下的空間一樣可以存別的東西。沒錯，這支隨身碟並沒有因為身負重任而不能進行他用——平常依舊可以當做普通的隨身碟來使用。</p><p>刷新了我的眼界一波，好傢伙！</p><h3 id="使用方法">使用方法</h3><p>從 <a href="https://github.com/ventoy/Ventoy">Ventoy 的 Github 項目</a>中下載並解壓縮，執行<code>Ventoy2Disk.exe</code>。</p><p><img src="/rufus-vs-ventoy/ventoy1.png" alt="ventoy1"></p><p>選擇你要設定的開機隨身碟，並點擊 Install。</p><p><img src="/rufus-vs-ventoy/Ventoy2.png" alt="Ventoy2"></p><p>然後就完成了。有夠簡單明瞭，也幾乎不用等待，真是愛了。</p><p>接下來就可以丟 iso 進去了，以我這邊為例丟了 Win10, Win11, Ubuntu 三個系統映像進去：</p><p><img src="/rufus-vs-ventoy/Ventoy3.png" alt="Ventoy3"></p><p>可以注意到，我裡面還亂丟了別的文件。有關係嗎？沒關係！如前所述，這支隨身碟依舊可以日常使用唷 :)</p>]]></content:encoded>
      
      
      <category domain="https://shuaixin.cc/categories/%E5%85%B6%E4%BB%96/">其他</category>
      
      
      <category domain="https://shuaixin.cc/tags/Ventoy/">Ventoy</category>
      
      <category domain="https://shuaixin.cc/tags/Rufus/">Rufus</category>
      
      
      <comments>https://shuaixin.cc/rufus-vs-ventoy/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>網際網路小筆記</title>
      <link>https://shuaixin.cc/internet-note/</link>
      <guid>https://shuaixin.cc/internet-note/</guid>
      <pubDate>Mon, 23 Dec 2024 16:00:00 GMT</pubDate>
      
        
        
          
          
      <description></description>
          
        
      
      
      
      <content:encoded><![CDATA[<h3 id="OSI-七層模型懶人包">OSI 七層模型懶人包</h3><ul><li>應用程式層：Http, DNS, POP3, Telnet, FTP, DHCP</li><li>展示層：轉碼解碼的都屬於此層</li><li>會議層：比較沒有存粹的會議層的例子</li><li>傳輸層：TCP, UCP</li><li>網路層：IP, ICMP（router比較負責這裡）</li><li>資料連接層：MAC, Wifi, Ethernet（bridge, switch, hub 比較負責這裡）</li><li>實體層：實體硬體基礎設施屬此層（repeater顯然是這裡咯）</li></ul><p>switch 跟 hub 的差別？switch 有記憶體，會負責記得所有設備的 mac 位置；但 hub 每次都用廣播的。</p><p>gateway 跟 router 的差別？在不同協議之間幫忙溝通的是 gateway，而 router 主要只負責 IP 協議內的事。其實可以把 router 想成是一種 IP gateway。</p><h3 id="UTP-STP">UTP, STP</h3><p>TP for Twisted-Pair，也就是雙絞線。而 U for Unshielded, S for Shielded。</p><p>雙絞線的好處是什麼？雙股螺旋互相纏繞，電流方向不固定，就不會產生明顯的磁力線，降低干擾。</p><h3 id="RJ45">RJ45</h3><p>RJ45 是一種接頭與插孔的標準，因有八個 position、八個 contact，所以也稱 8P8C。</p><p>我們現在的乙太網線就採用此規格。</p><h3 id="T568A-T568B">T568A, T568B</h3><p>那咱網路線的 8P8C 怎麼排列與對接呢？現在比較常用 T568B 的協定標準。</p><h3 id="ARP">ARP</h3><p>ARP(address resolution protocol) 是哪層？ARP table 記得 ip 跟 mac 的對應。如果沒有，就廣播問一下，問完就記起來。所以是哪層？偏資料連接層，但其實網路層也算。用戶端主機跟 switch 都會維護 ARP table。</p><h3 id="Localhost">Localhost</h3><p>localhost 就是 127.0.0.1，你 ping 這個位置，網路層會直接回答你。</p><p>也就是說，實體層跟資料連接層都完全不參與其中。網卡不會收到這個請求，所以資料也不會流經網路線。</p><p>那 127.0.0.2 有用嗎？其實整個 127.0.0.0/8 都是保留的回送地址，但習慣上我們只用 127.0.0.1。</p><h3 id="0-0-0-0">0.0.0.0</h3><p>我第一次連 wifi 時，我還沒被分配 IP 位置，那我要怎麼發送訊息？此時我的 IP 是 0.0.0.0，而我的目的位置是 256.256.256.256，也就是廣播跟大家說嗨這裡是新設備唷，誰可以給我配發一個內網 IP 呀？</p><p>然後這時候你的 router 就可以作為一個 DHCP 伺服器配一個 IP 給你。</p><h3 id="快速判斷ABC類網路">快速判斷ABC類網路</h3><p>先看二進制的開頭。0開頭就是A、10開頭就是B、110開頭就是C。（1110開頭就是D、1111之後就是E）</p><h3 id="CIDR（Classless-Inter-Domain-Routing）">CIDR（Classless Inter-Domain Routing）</h3><p>重點在於 Classless。</p><p>如果按照最原始的設定，今天你作為 ISP 要把 IP 分配給用戶，當你發了一個 C 類網路如 220.128.133.0/24 出去，一次就用掉了 256 個排列組合，有夠浪費的啦。</p><p>於是 CIDR 就可以拿來打破類別枷鎖，我們不管 C 類的遮罩規定了，我發 220.128.133.0/32 就好！一次只發一個位置，這樣我就可以發給更多人用了。</p><h3 id="Private-IP">Private IP</h3><p>A、B、C類各有這三段：10.0.0.0/8、172.16.0.0/12、192.168.0.0/16</p><p>A類跟C類很簡單，分別就是 10.x.x.x 跟 192.168.x.x。</p><p>而B類的遮罩是12bit，不太直觀，是 172.16.x.x-172.31.x.x。</p><h3 id="NAT">NAT</h3><p>NAT(network address translation) 負責把 private IP 置換成 public IP 出去，回來反之。 因為是改 IP 的標頭，所以是網路層。但其實內網很多設備同時要訪問外網，這時候同一個 IP 沒辦法同時處理，此時其實會修改到埠號，而埠號就是TCP的活了，所以也會碰到傳輸層。</p><p>例如 port forwarding 就是 NAT 在負責的。我們先告訴 NAT 說如果外網要求訪問某個 port（TCP 負責的埠），那我就給他某個內網的某個 port。</p><p>Port 就是 TCP、UDP 在負責的，乃傳輸層。常見的如 80 for http, 21 for ftp, 22 for ssh, 25 for smtp(e-mail)。</p><h3 id="CSMA-CD-CSMA-CA">CSMA/CD, CSMA/CA</h3><p>CSMA/CD 是有線的 Ethernet 用的，是 Collision Detection，都發送看看，碰撞再說。</p><p>CSMA/CA 則是無線的 Wifi 用的，是 Collision Avoidance，我發之前會問也會警告大家不要來碰撞。</p><h3 id="IaaS-PaaS-SaaS">IaaS, PaaS, SaaS</h3><p>IaaS, PaaS, SaaS 分別是「Infrastructure as a Service」、「Platform」、「Software」。你跟 google GCP 租虛擬機就是 IaaS；你用 Heroku 假設一個 linebot 的後台就是 Paas；你用 gmail 就是接受 SaaS。</p><h3 id="其他">其他</h3><p>STP（Spanning Tree Protocol, 生成樹協議）因為實際上網路不總是樹狀拓撲，STP 會算出一棵樹，可以避免掉死回圈。</p>]]></content:encoded>
      
      
      <category domain="https://shuaixin.cc/categories/%E5%85%B6%E4%BB%96/">其他</category>
      
      
      <category domain="https://shuaixin.cc/tags/internet/">internet</category>
      
      
      <comments>https://shuaixin.cc/internet-note/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>停止 Windows 自動更新</title>
      <link>https://shuaixin.cc/stop-windows-auto-update/</link>
      <guid>https://shuaixin.cc/stop-windows-auto-update/</guid>
      <pubDate>Thu, 19 Dec 2024 16:00:00 GMT</pubDate>
      
        
        
          
          
      <description></description>
          
        
      
      
      
      <content:encoded><![CDATA[<h3 id="停止-Windows-自動更新">停止 Windows 自動更新</h3><p>眾所周知，微軟並不希望我們把 windows 的自動更新關掉。即使系統裡面提供了關閉選項，依舊也只能「暫緩」一段時間。</p><p>但自動更新就很討厭，反正我就是要關掉。</p><p>下面這套方法用的邏輯是：好啊反正你就是不讓我「關掉」自動更新，那我把更新的位置換成本地，你就不可能獲得更新內容了。</p><blockquote><p>注意此篇辦法需使用「本機群組原則編輯器」，只有 Windows 專業版才有。若是家用版，則此篇不適用。</p><p>Win10、Win11 經測試皆可成功。</p></blockquote><h3 id="詳細步驟">詳細步驟</h3><p>首先我們 <code>windows+R</code> ，輸入 <code>gpedit.msc</code> 並執行。</p><p><img src="/stop-windows-auto-update/stop-windows-update-1.PNG" alt="stop-windows-update-1"></p><p>執行後我們打開了本機群組原則編輯器。此處我們從左邊側邊欄打開 <code>電腦設定 &gt; 系統管理範本 &gt; Windows元件 &gt; Windows Update</code> ，就可以找到如圖的「指定近端內部網路 Microsoft 更新服務的位置」，雙擊打開。</p><p><img src="/stop-windows-auto-update/stop-windows-update-4.png" alt="stop-windows-update-4"></p><p>將它啟用，並在選項中三個欄位都填入 <code>localhost</code> 後點擊確定。如此一來，windows 就會跟本地找更新資料，但我們根本不會給它。耶。</p><p><img src="/stop-windows-auto-update/stop-windows-update-5.png" alt="stop-windows-update-5"></p><p>在同一個頁面中，我們找到「不要連線到任何 Windows Update 網際網路位置」，一樣雙擊打開。</p><p><img src="/stop-windows-auto-update/stop-windows-update-6.png" alt="stop-windows-update-6"></p><p>這裡我們啟用，並點擊確定。</p><p><img src="/stop-windows-auto-update/stop-windows-update-7.png" alt="stop-windows-update-7"></p><p>完成！</p><h3 id="順便把-Microsoft-Defender-給關了">順便把 Microsoft Defender 給關了</h3><p>既然我們都來本機群組原則編輯器了，如果你也覺得 Defender 很煩的話，那我們不妨就順便把它關掉吧 :)</p><p>來到 <code>電腦設定 &gt; 系統管理範本 &gt; Windows元件 &gt; Microsoft Defender防毒軟體</code> ，雙擊「關閉 Microsoft Defender 防毒軟體」。</p><p><img src="/stop-windows-auto-update/stop-windows-update-2.png" alt="stop-windows-update-2"></p><p>在這裡，我們一樣啟動，並雙擊確定。</p><p><img src="/stop-windows-auto-update/stop-windows-update-3.png" alt="stop-windows-update-3"></p><p>完成！</p><p>然而，根據經驗，其實這裡可能只是關心酸的。因為 Defender 沒過多久又會自己復活……</p><p>不過其實 Defender 有一個簡單的閉閉方法，就是裝另一個第三方防毒軟體就可以咯。</p>]]></content:encoded>
      
      
      <category domain="https://shuaixin.cc/categories/%E5%85%B6%E4%BB%96/">其他</category>
      
      
      <category domain="https://shuaixin.cc/tags/Windows/">Windows</category>
      
      
      <comments>https://shuaixin.cc/stop-windows-auto-update/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>勞動力發展署北基宜花金馬分署物聯網AI系統整合實務筆試詳解</title>
      <link>https://shuaixin.cc/iot-exam-note/</link>
      <guid>https://shuaixin.cc/iot-exam-note/</guid>
      <pubDate>Mon, 25 Nov 2024 16:00:00 GMT</pubDate>
      
        
        
          
          
      <description></description>
          
        
      
      
      
      <content:encoded><![CDATA[<p>以下題目為「勞動力發展署北基宜花金馬分署 113 年度自辦職前訓練：物聯網-AI 系統整合實務（泰山）第 1 期考題」。</p><p>而以下詳解都是我自己隨手寫下的，僅供參考咯。</p><p>當然，如果有誤還請提點，感謝！</p><h3 id="題目與解析">題目與解析</h3><blockquote><p><strong>電腦網路 OSI 模型的資料鏈結層（data link layer）可以識別下列何者？</strong><br>① 應用系統所採用的 HTTP 或 FTP 等通訊協定<br>② 傳輸時所使用的媒體規格<br>③ 網路卡的實體位址（MAC address）<br>④ 電腦的 IP 位址</p></blockquote><p>某種程度上的網際網路背誦題。七層結構的常見懶人包如下：</p><ul><li>應用程式層：Http, DNS, POP3, Telnet, FTP, DHCP</li><li>展示層：轉碼解碼的都屬於此層</li><li>會議層：比較沒有存粹的會議層的例子</li><li>傳輸層：TCP, UCP</li><li>網路層：IP, ICMP（router比較負責這裡）</li><li>資料連接層：MAC, Wifi, Ethernet（bridge, switch, hub 比較負責這裡）</li><li>實體層：實體硬體基礎設施屬此層（repeater顯然是這裡咯）</li></ul><p>故此題選 MAC address。</p><p>switch 跟 hub 的差別？switch 有記憶體，會負責記得所有設備的 mac 位置；但 hub 每次都用廣播的。</p><p>gateway 跟 router 的差別？在不同協議之間幫忙溝通的是 gateway，而 router 主要只負責 ip 協議內的事。其實可以把 router 想成是一種 ip gateway。</p><p>ARP(address resolution protocol) 是哪層？ARP table 記得 ip 跟 mac 的對應。如果沒有，就廣播問一下，問完就記起來。所以是哪層？偏資料連接層，但其實網路層也算。用戶端主機跟 router 都會維護 ARP table。</p><p>NAT(network address translation) 負責把 private ip 置換成 public ip 出去，回來反之。 因為是改 IP 的標頭，所以是網路層。但其實內網很多設備同時要訪問外網，這時候同一個ip沒辦法同時處理，此時其實會修改到埠號，而埠號就是TCP的活了，所以也會碰到傳輸層。</p><p>例如 port forwarding 就是 NAT 在負責的。我們先告訴 NAT 說如果外網要求訪問某個 port（TCP 負責的埠），那我就給他某個內網的某個 port。</p><p>Port 就是 TCP、UDP 在負責的，乃傳輸層。常見的如 80 for http, 21 for ftp, 22 for ssh, 25 for smtp(e-mail)。</p><blockquote><p><strong>網際網路的通訊方式是採用何種資料交換技術？</strong><br>① 封包交換（packet switching）<br>② 電路交換（circuit switching）<br>③ 數位交換（digital switching）<br>④ 訊息交換（message switching）</p></blockquote><p>這題基本，選封包。</p><blockquote><p><strong>「資料完整性檢查」必須使用到下列哪一種技術？</strong><br>① 金鑰系統<br>② 加密<br>③ 雜湊函數<br>④ 解密</p></blockquote><p>這題選項露餡，加密解密跟金鑰不都一家人嗎？所以腦選雜湊函數。</p><blockquote><p><strong>下列何種記憶體技術，將部分程式暫時儲存於硬式磁碟上，於需要執行之時再進行資料交換（swap）？</strong><br>① 堆疊（stack）記憶體<br>② 佇列（queue）記憶體<br>③ 快取（cache）記憶體<br>④ 虛擬（virtual）記憶體</p></blockquote><p>swap 技術使用的是虛擬記憶體，因為當初即如此命名，比較是名詞定義問題。</p><blockquote><p><strong>駭客發送大量封包，以癱瘓被攻擊者的網路或伺服器，稱為何類攻擊手法？</strong><br>① 邏輯炸彈（Logic Bomb）<br>② 阻斷服務（Denial of Service）<br>③ 巨集病毒（Macro Virus）<br>④ 網路入侵（Network Intrusion）</p></blockquote><p>DDoS 挺常見的，英雄聯盟 S24 世界大賽前，T1 就一直被 DDOS 攻擊。所以選 DoS（蛤）。至於多一個 D 是 Distributed，表示分散式阻斷。其運用各地不同的一堆用戶端發出大量的請求來癱瘓服務器。而畢竟對伺服器來說都是合法的請求（不是少數幾台在大量索求），所以防不勝防。</p><blockquote><p><strong>有關 NOR 閘之敘述，下列何者錯誤？</strong><br>① 先執行 NOT 運算，結果再做 OR 運算<br>② 所有輸入皆為 0 時，輸出才為 1<br>③ 是一種通用邏輯閘（Universal Gate）<br>④ 能夠模擬出 NOT 運算閘</p></blockquote><p>邏輯閘題。Nor 即 Not-OR，就是或閘的相反，其真值表為 001、010、100、110。</p><p>顯然是先或運算再非運算。</p><blockquote><p><strong>下列何者為 CPU 執行指令的正確順序？</strong><br>① 取指令、分析指令、執行、取資料<br>② 取指令、取資料、分析指令、執行<br>③ 取資料、取指令、分析指令、執行<br>④ 取指令、分析指令、取資料、執行</p></blockquote><p>又是一題選項露餡，所以我們只需抉擇「取資料」與「分析指令」之先後。</p><p>試想，並不是每筆指令都需要取資料，所以分析指令的種類顯然必須在先。故選「取指令 → 分析指令 → 取資料 → 執行」。</p><p>認真點講，其實這題就是所謂的「Fetch-Decode-Execute Cycle」。</p><blockquote><p><strong>將運算元的值直接編碼在指令中的是哪一種定址模式？</strong><br>① 暫存器定址（register addressing）<br>② 立即定址（immediate addressing）<br>③ 位移定址（displacement addressing）<br>④ 直接定址（direct addressing）</p></blockquote><p>可能要理解組合語言的邏輯？</p><p>暫存器定址就是直接指定CPU身上的暫存器，讀取速度快，如<code>MOV R1, R2; 把R2的內容放到R1</code>。</p><p>立即定址就是我直接指定某個位置要放某個立即數，比如說<code>MOV R1, 5; 把5這個數字存在R1</code>。（運算元5直接寫在指令裡咯，故選）</p><p>直接定址其實就是指標的概念，如<code>MOV R1, [1000h] ; 將內存地址 1000h 中的值存入 R1</code>。</p><p>位移定址也是指標，但加了 offset，例如<code>MOV R1, [1000h + 4] ; 將 1000h + 4 指向的值存入 R1</code>。</p><blockquote><p><strong>傳統 IP（Internet Protocol）位址包含網路位址與主機位址，網路位址用來辨別所屬的網路；假設網路位址為 140.112，請問有多少 IP 位址可以用來識別網路上的裝置？</strong><br>① 65536<br>② 1024<br>③ 16384<br>④ 32768</p></blockquote><p>這裡的「傳統IP」應該是指 IPv4 吧 XD</p><p>那反正 IP 全長就是 140.112.x.x，後面作為 host ID，共有 16bit，故有 65536 種可能。不過需注意，140.112.0.0 跟 140.112.255.255 會保留不可使用，嚴謹來說是 65534 個可用的地址。</p><blockquote><p><strong>在微處理機中，下列何者負責記錄 CPU 下一個所要執行的指令在記憶體中的位址？</strong><br>① 堆疊指標（stack pointer）<br>② 指令暫存器（instruction register）<br>③ 累加器（accumulator）<br>④ 程式計數器（program counter）</p></blockquote><p>單純是名詞題，就 CPU 按照順序接續執行指令的過程中，會有人在旁邊幫忙數，這人叫 program counter。</p><blockquote><p><strong>硬體上大單元的 ALU，其主要功能為何？</strong><br>① 監控螢幕顯示<br>② 執行磁碟存取<br>③ 執行加法、減法與邏輯運算<br>④ 執行記憶體中的資料傳輸</p></blockquote><p>考首字母縮寫？ALU 是運算邏輯單元，負責運算。</p><blockquote><p><strong>十進位數字 256 減去二進位數字 10001101 後的結果為何？</strong><br>① 十進位的 114<br>② 二進位的 01110011<br>③ 十進位的 36<br>④ 二進位的 01111010</p></blockquote><p>就是 256-141=115。</p><blockquote><p><strong>下列有關並列（Parallel）傳輸和序列（Serial）傳輸的比較，何者有誤？</strong><br>① 並列傳輸一次能傳送較多的資料<br>② 序列傳輸相對的成本較低<br>③ 電腦的 USB 和 SATA 介面都是採用序列傳輸<br>④ 電腦網路大多是透過並列傳輸的方式來傳送資料</p></blockquote><p>兄弟們，USB 是「通用序列匯流排」，S for Serial；而 SATA 的 S 也是 Serial，名字露餡。</p><p>不過只要涉及長距離溝通（超過一個主機板的距離就算很長了），基本上都是用序列的方法，一個時脈只走一個bit。</p><p>所以網路是用序列才對哦。</p><blockquote><p><strong>計算二進位值「1111010111.101」，轉換成十六進位值的結果為何？</strong><br>① 3D7.A<br>② 32C.5<br>③ D25.3<br>④ 259.E</p></blockquote><p>主要是小數點下面對十進制使用者來說都很不直觀，要換算一下。</p><p>0b0.101 換算成十進制是 0.625，也就是 10/16，所以選 0.A 那位。</p><p>沒錯，整數部分不用管，誰理你呀！</p><blockquote><p><strong>下列哪個網路卡實體位址（MAC Address）正確的表示方式？</strong><br>① E2-C3-01-22-97-F4<br>② A3:45:CF:00:00:01:58:DC<br>③ 254. 73. 45. 69<br>④ 67:02:AB:33</p></blockquote><p>這題究極無敵霹靂無聊！反正規範是六個字節。重點是習慣上我們明明就是用冒號相隔，所以這題明顯又無聊又愛騙。</p><blockquote><p><strong>國際標準組織（ISO）所訂定之開放式系統連結（OSI）的參考模式中，其通訊協定第一（底）層為？</strong><br>① 網路層<br>② 資料鏈路層<br>③ 實體層<br>④ 運送層</p></blockquote><p>OSI 背誦題，底層為實體層。</p><blockquote><p><strong>以下何者不是動態網頁中使用的腳本語言？</strong><br>① JavaScript<br>② ASP<br>③ PHP<br>④ PWS</p></blockquote><p>小白過濾題（？），因為 PWS 是一種軟體，不是語言。</p><blockquote><p><strong>在記憶體的階層式（memory hierarchy）架構中，下列那一個的存取時間最短？</strong><br>① CPU 暫存器（register）<br>② 主記憶體（main memory）<br>③ 快取記憶體（cache memory）<br>④ 硬碟（hard disk）</p></blockquote><p>離 CPU 越近越快，故。</p><blockquote><p><strong>下列敘述何者正確？</strong><br>① 乙太網路中的電腦，每次要傳送訊框時都要用 CSMA/CA 方法爭取傳送的機會<br>② 交換式集線器(Switch)可以減少乙太網路資料傳送時，發生碰撞(Collision)的情形<br>③ 乙太網路通常採環狀(Ring)的架構<br>④ Wifi 無線網路是採用乙太網路的邏輯機制建構的</p></blockquote><p>CSMA/CD 是有線的 Ethernet 用的，是 Collision Detection，都發送看看，碰撞再說。</p><p>CSMA/CA 則是無線的 Wifi 用的，是 Collision Avoidance，我發之前會問也會警告大家不要來碰撞。</p><p>Ethernet 用的是星狀拓撲或總線拓撲。</p><blockquote><p><strong>假定有一個一維陣列 A，陣列中每個元素需占用 4 個位元，如果程式執行時 A(60) 的記憶體位址為 600，則 A(310) 的位址為何？</strong><br>① 3100<br>② 1600<br>③ 1240<br>④ 1840</p></blockquote><p>等差數列題（？），相差了 1000 個位元，故選 1600。</p><blockquote><p><strong>Unicode 可容納 65536 個字符編號，包括 128 個 ASCII 字元、英文、中文、日文及非英語系國家常用文字，其係利用多少位元組來表示？</strong><br>① 1<br>② 2<br>③ 3<br>④ 4</p></blockquote><p>換句話說，65536 個資訊，需要至少幾 byte 來容納？需要 16bit 共 2byte。</p><blockquote><p><strong>假設電腦內部整數佔用 16 位元，採用 1 的補數(1’s complement)表示法，則所能表示的整數範圍為：</strong><br>① -32767 到 32767<br>② -32767 到 32768<br>③ -32768 到 32767<br>④ -32768 到 32768</p></blockquote><p>1補數：對人類來說比較直觀，6（0b0110）的相反數-6就直接寫成 0b1001，全部 Not 掉就好。但這樣會讓 0b0000 跟 0b1111 都是 0。</p><p>2補數：算法上會比較簡單，少一個步驟且不用特別設計減法ALU。6（0b0110）的相反數-6是0b1001+1=0b1010。</p><p>此題最大正數是 0111111111111111，最小是 1111111111111111。 故為正負 32767。</p><blockquote><p><strong>下列何種網頁技術是在客戶端(client)的瀏覽器(browser)上執行？</strong><br>① JavaScript<br>② ASP<br>③ PHP<br>④ CGI</p></blockquote><p>前端語言 HTTP, CSS, JS，選 JS。</p><blockquote><p><strong>下列有關 P2P(peer-to-peer) 網路的敘述，何者錯誤？</strong><br>① 一般而言，P2P 網路內，每一部電腦都具有 Server 與 Client 的身份<br>② P2P 網路內，通常有一部以上的 Server 提供 P2P 服務<br>③ P2P 網路內，通常有一部以上的 Client 要求 P2P 服務<br>④ Server 的角色極為重要，所以若某一部 Server 故障，將導致整個 P2P 網路停止運作</p></blockquote><p>同學們，遇到「極限用語」就當錯。「整個」為極限用語，視為錯。（不要教壞小孩）</p><blockquote><p><strong>下列哪一個 IP 位址是屬於 B 級網路的等級？</strong><br>① 62.100.5.2<br>② 129.17.22.25<br>③ 193.6.8.5<br>④ 210.99.56.32</p></blockquote><p>背誦題，好無聊。第一個字節開頭 0 為 A級、10為B級、110為C級。十進制而言，127以內為A級、191以內為B級。</p><blockquote><p><strong>請問十進位數字 125.125，轉為二進位數字的結果為何？</strong><br>① 1111011.110101<br>② 1111111.110101<br>③ 1011111.010101<br>④ 1111101.001</p></blockquote><p>0.125 為 1/8，所以小數點後面是 0.001。喔喔？整數又不用看了，咖薰。（出題老師很心機哦，給個讚。這種可以鑒別小聰明的心機才是良性心機）</p><blockquote><p><strong>使用多個處理器但彼此間並不共享記憶體和時脈的作業系統是：</strong><br>① 批次作業系統<br>② 多工式作業系統<br>③ 即時作業系統<br>④ 分散式作業系統</p></blockquote><p>你知道分散式跟平行式的差別嗎？平行式會共用時脈哦！偶爾甚至會共用記憶體。但這些都是寫死在 CPU 架構裡面了。</p><blockquote><p><strong>下列網路傳輸設備中，何者是用來將網路訊號增強後再送出？</strong><br>① 橋接器 (bridge)<br>② 中繼器 (repeater)<br>③ 路由器 (router)<br>④ 交換器 (switch)</p></blockquote><p>陳冠宇算是一種中繼投手嗎？</p><blockquote><p><strong>資訊安全中最重要的三項目標為 CIA，其中 C 是保密性 (Confidentiality)，I 是完整性 (Integrity)，A 是代表什麼？</strong><br>① 存取 (Access)<br>② 可用性 (Availability)<br>③ 證實 (Affirmation)<br>④ 匿名 (Anonymity)</p></blockquote><p>我原本選了證實QQ 我想說都要MD5之類的校驗一下才對，但其實校驗就是完整性校驗啊，就是完整性的範疇了。其實「可用性」也很重要，否則第三方秉持著「我破解不了但我要毀了你們！」的心態，直接讓資訊對大家都不可用，那也不好。</p><blockquote><p><strong>OSI 網路七層架構中，哪一層服務負責控制傳送的路徑 (Routing)？</strong><br>① 實體層 (Physical Layer)<br>② 資料鏈結層 (Data Link Layer)<br>③ 網路層 (Network Layer)<br>④ 傳輸層 (Transport Layer)</p></blockquote><p>見第一題，routing 就是在搞 IP，所以跟 IP 一起。</p><blockquote><p><strong>在 ASCII 碼中，字元 H 的十六進位表示為 48，請問字元 K 的十六進位表示為何？</strong><br>① 50<br>② 51<br>③ 4A<br>④ 4B</p></blockquote><p>英文字母都是連號，連過去就對了，但記得要十六進制，選 4B。</p><blockquote><p><strong>下列哪一項為電腦中實際使用的負數表示法？</strong><br>① 浮點數表示法<br>② 最高位元表示法<br>③ 1 補數法<br>④ 2 補數法</p></blockquote><p>見…… 忘了第幾題了，我複製過來吧：</p><p>1補數：對人類來說比較直觀，6（0b0110）的相反數-6就直接寫成 0b1001，全部 Not 掉就好。但這樣會讓 0b0000 跟 0b1111 都是 0。</p><p>2補數：算法上會比較簡單，少一個步驟且不用特別設計減法ALU。6（0b0110）的相反數-6是0b1001+1=0b1010。</p><blockquote><p><strong>下列關於網路伺服器的描述，何者正確？</strong><br>① Proxy Server：具有快取功能，加快網頁開啟速度<br>② FTP Server：可以登入遠端伺服器<br>③ DNS Server：可動態分配 IP 位址<br>④ DHCP Server：負責 IP 位址與網域名稱的轉換</p></blockquote><p>FTP 是檔案傳輸；DNS 跟 DHCP 兩個寫反了。</p><blockquote><p><strong>電子商務交易中，參與的角色是企業與其相關夥伴，是屬於下列哪一種型態？</strong><br>① B2B<br>② B2C<br>③ C2C<br>④ G2G</p></blockquote><p>其中 G2G 應該是政府對政府的意思……吧？不確定，請告訴我。</p><blockquote><p><strong>下列有關程式語言之敘述，何者不正確？</strong><br>① 組合語言為低階語言<br>② JAVA 程式可以不依附作業系統執行<br>③ 物件導向語言具封裝、繼承與多型特性<br>④ 組合語言不需要翻譯即可以執行</p></blockquote><p>組合語言也需要組譯器翻譯。</p><blockquote><p><strong>IP 公共位址是利用下列何種協定，可讓多部使用私人 IP 位址的電腦，共同使用一個實體 IP 位址上網路？</strong><br>① TCP<br>② RIP<br>③ DHCP<br>④ NAT</p></blockquote><p>TCP 是傳輸層；RIP 負責 routing 的邏輯，比較是網路層；DHCP 負責分配 IP 給大家，但是是應用層（比較複雜啦我也不知道，嘻嘻）；NAT 負責讓多個用戶端共用 IP，比較偏網路層。</p><blockquote><p><strong>有一應用程式需要以一個變數來表示一年 365（或 366）天中的一天，請問該變數至少需要多少位元組？</strong><br>① 1<br>② 2<br>③ 8<br>④ 9</p></blockquote><p>1byte 256嘛，所以至少2byte。</p><h3 id="補充">補充</h3><p>IaaS, PaaS, SaaS 分別是「Infrastructure as a Service」、「Platform」、「Software」。你跟 google GCP 租虛擬機就是 IaaS；你用 Heroku 假設一個 linebot 的後台就是 Paas；你用 gmail 就是接受 SaaS。</p><p>STP（Spanning Tree Protocol, 生成樹協議）因為實際上網路不總是樹狀拓撲，STP 會算出一棵樹，可以避免掉死回圈。</p>]]></content:encoded>
      
      
      <category domain="https://shuaixin.cc/categories/%E5%85%B6%E4%BB%96/">其他</category>
      
      
      <category domain="https://shuaixin.cc/tags/internet/">internet</category>
      
      <category domain="https://shuaixin.cc/tags/iot/">iot</category>
      
      
      <comments>https://shuaixin.cc/iot-exam-note/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>讀書筆記：《大腦簡史》</title>
      <link>https://shuaixin.cc/Brief-History-of-Brain/</link>
      <guid>https://shuaixin.cc/Brief-History-of-Brain/</guid>
      <pubDate>Tue, 12 Nov 2024 16:00:00 GMT</pubDate>
      
        
        
          
          
      <description></description>
          
        
      
      
      
      <content:encoded><![CDATA[<p><img src="/Brief-History-of-Brain/danaojianshi.jpeg" alt="danaojianshi"></p><h3 id="先有神經傳導素還是先有受器？">先有神經傳導素還是先有受器？</h3><p>透過 DNA 定序發現，早在植物跟動物分家之前，就已經存在一種麩氨酸受器了。這種受器一開始可能就單純在找營養物質而已。</p><h3 id="化學訊號的發現">化學訊號的發現</h3><p>Sherrington 認為除了電傳遞以外，神經細胞之間應該有著間隙（並命名為「突觸」），且可能是透過化學的方式調控。</p><p>後來是 Loewi 證明了這件事。他挖了兩個活跳跳的青蛙心臟，一個接著迷走神經，一個沒有。他刺激迷走神經讓其中一個心跳變慢，然後把周圍的液體拿去澆在另一顆心臟上——也成功減慢了心跳。可知其中必有化學物質參與。</p><h3 id="遞弱代償">遞弱代償</h3><p>作者在註解處提醒讀者，單細胞走向多細胞並不是一種進化，而是演化上的「偶然」，進而走向的一條不歸演化分支。王東嶽的《物衍通論》提到，複雜度越高的生命體其生存力反而越弱，因此「遞弱代償」出現了，我們必須發展出各式各樣的能力來補償這個缺陷。</p><h3 id="神經細胞奴役了其他細胞">神經細胞奴役了其他細胞</h3><p>如同 Harari 在《人類大歷史》的「分工與農業革命造成人類悲劇」，其實細胞也一樣。從單細胞發展成多細胞的過程中，在名為分工的美名之下，大部分細胞都成為了神經細胞的共生囚犯。</p><h3 id="比海綿更古老的多細胞動物">比海綿更古老的多細胞動物</h3><p>以前學過海綿自成一個海綿動物門，雖是多細胞生物但其實比較像是群聚的單細胞，缺乏系統分工，當然就沒有神經系統。</p><p>所以帶有神經系統的「櫛水母」就一直被歸類在刺絲胞動物門裡面，以為也是一種水母。但後來發現不對，櫛水母不是水母，他可能甚至比海綿更早出現，是最古老的多細胞動物。</p><p>仔細研究櫛水母的神經系統，居然也不同於其他所有動物（其他都是跟水母差不多的基礎機制）。所以目前認為，動物的神經系統可能有兩次的獨立起源。</p><p>櫛水母目前自成<strong>櫛板動物門</strong>。</p><h3 id="神經細胞退守中央">神經細胞退守中央</h3><p>隨著神經系統主掌大權，我們可以看到感覺神經本體越躲越裡面：</p><ul><li>蚯蚓（環節動物門）的感覺神經細胞本體就直接在表皮上</li><li>蝸牛（軟體動物門）的移動到表皮底下</li><li>魚（脊椎動物門）的跑到脊椎附近</li><li>兩棲綱、爬蟲綱、鳥綱、哺乳綱的直接躲到背根神經節裡面</li></ul><h3 id="寒武紀大爆發的成因還在吵">寒武紀大爆發的成因還在吵</h3><p>關於「寒武紀大爆發」，當年達爾文就在《物種起源》打預防針：「這個我也解釋不了，我的反對者可能會拿寒武紀大爆發來反駁我。」（演化應是漸進而緩慢的過程）</p><p>我自己高中學到的版本是，因為五億年前總算累積足夠的氧氣濃度，進而形成了臭氧層，隔絕了致命的紫外線強度，生物們開始登陸，蓬勃發展。</p><p>但其實至今尚無學界定論，很有可能所謂的生物大爆發其實只是「化石大爆發」罷了。即，其實只是剛好當時開始發展硬殼這個生存策略，所以才開始有化石被保留下來。</p><p>帕克的「光開關」理論認為，當時三葉蟲首開先例開了天眼（感光能力），視覺橫空出世，一時間成了鬼神級的掠食者。因為掠食者的出現，生存壓力頓時飛速上升，其他物種就被逼得開始快速適應，於是「硬殼」就這樣出來了。然後我們才透過化石看到了這樣的蓬勃發展。</p><h3 id="無意識的費洛蒙攻擊">無意識的費洛蒙攻擊</h3><p>除了主要的嗅覺系統，「犁鼻器」也會接收氣味分子並且傳入嗅球。但犁鼻器的訊息不會進一步走到嗅覺皮質，所以我們不會意識到這部分的資訊。</p><p>目前認為，犁鼻器可能就是費洛蒙接收器。</p><p>有蹄類、貓科動物有所謂的「裂唇嗅反應」，就是為了讓犁鼻器聞得更清楚做出的動作。</p><p>除了犁鼻器，我們其實還發現了第零對腦神經，作用不詳，但就解剖學上的研究來看，可能是原始的「嗅覺」，負責調節性行為。（引號是要注意此處是指廣義上的嗅覺，也就是化學受器）至於為什麼明明發現了多出來的這對腦神經我們卻不教，作者也表疑惑。</p><h3 id="聽音辨位的邏輯">聽音辨位的邏輯</h3><p>如何聽音辨位？</p><ul><li>左右：時間差跟音量差</li><li>上下：透過耳廓的上下不對稱的形狀，聲學上的反射造成的差異</li><li>前後：後方明顯聲音品質會不一樣</li></ul><p>於是Z軸生物如貓頭鷹，他們耳朵在水平高度上是不對稱的！（那其他的鳥呢？）</p><h3 id="為什麼視神經要交叉？">為什麼視神經要交叉？</h3><p>為什麼視神經交叉要交叉？因為這樣比較方便往反方向逃跑！同理，感覺神經大多數也都是傳給對側大腦。</p><p>那為什麼隨意肌多數是對側支配？作者表示，演化後期「順勢」就這樣子了。</p><h3 id="第三隻眼">第三隻眼</h3><p>松果體在其他的脊椎動物身上（如鯊魚、青蛙、蜥蜴）都能直接透過顱頂眼（第三隻眼）來接收光線，調節晝夜節律。但人類不行，甚至成人的松果體常常會鈣化。不過松果體依然透過視神經傳來的訊號，再由褪黑激素來調節晝夜節律。</p><p>話說笛卡爾花了許多時間研究松果體，因為他在腦中央，而且只有一顆，笛卡爾就認為他是靈魂跟身體的連接點。（畢竟人家是心物二元論）</p><h3 id="弱化的咀嚼肌造就了更發達的腦">弱化的咀嚼肌造就了更發達的腦</h3><p>透過一些基因或因其造成的疾病的觀察，也許我們可以窺視一下人腦是怎麼正向突變而成現在這樣的：</p><ul><li>RNF213 缺失會導致毛毛樣腦血管病（腦部血流供應不足，以至於微血管代償性地增長）。也許一開始就是這個基因，讓我們的頸動脈的直徑擴張。</li><li>SLC2A1 負責葡萄糖轉運子（負責讓細胞吸收葡萄糖）的表達，而我們的 SLC2A1 在大腦內的表達比黑猩猩多出三倍，同時，身體其他位置的則低了六成。（大腦很貪心餒）</li><li>ASPM 如果異常會導致小顱畸形症。這可能是讓我們大腦容量變大的基因。</li><li>MYH16 在人類中失活了，但靈長類同學們充分地表達了它。它負責咀嚼肌的肌球蛋白！所以人類的咀嚼肌其實是相對弱很多的，但這也讓我們的顱骨壓力沒那麼大，可能間接使我們的大腦可以發展地更大顆。（這個跟已知用火有相輔相成的關係，可能是開始吃熟食之後我們才能如此犧牲咬合力）</li></ul><h3 id="骨盆變窄不是人類早產的主因">骨盆變窄不是人類早產的主因</h3><p>產科兩難假說（obstetric dilemma）認為，人類之所以早產，是因為人類開始直立行走後，骨盆縮小了，但人的頭變大了，怎麼解決？只好早產。</p><p>然而，我們發現骨盆腔的大小其實不會影響行走的效率（拿男女對比可知）。所以目前流行代謝交叉假說（metabolic crossover），就是人的大腦太耗能了，媽媽負擔不起了，只好早產出來。</p><h3 id="北歐國家比較沒有乳糖不耐症">北歐國家比較沒有乳糖不耐症</h3><p>本來人類在成年後，乳糖酶的活性就會下降甚至消失，但隨著畜牧業的發展，能喝奶就成了優勢。我們可以看到，乳製品業發達的北歐，比起東亞，就有較高比例的乳糖耐受超能力者。</p><h3 id="零散知識點">零散知識點</h3><ul><li>25°的水中，低濃度的氧氣分子想透過擴散作用來移動十公分的距離，必須花費大約27天！</li><li>已知發現最早的多細胞生物化石，其年代在 21 億年前。</li><li>黏菌（一開始被以為是真菌的原生生物，他的英文俗名是 Slime Mold，史萊姆黴菌）平常沒事的時候是單細胞，要繁殖或是要遷徙的時候，會群聚成多細胞形態。</li><li>一個感覺細胞+一個中間細胞就可以形成簡單的記憶；一對感覺細胞+一對中間細胞+一對抑制細胞就可以做出簡單的決策。</li><li>不需要的器官乾脆吃掉是很合理的演化方向。於是神經系統的發展過程中，在一些物種上看得出不被尊重的痕跡：<ul><li>海鞘找到附著處後就把腦袋吸收再利用不動腦了。</li><li>有些貝類明顯頭部退化</li></ul></li><li>貓科動物都沒有甜味味覺，因為他們是純肉食動物，不需要。</li><li>五感之中，只有嗅覺不經過視丘。合理，因為它最古老。</li><li>魚不會說話？其實魚會透過快速充放魚鰾來發出聲音。</li><li>嬰兒學習語言的方式，可能跟「音素的相連機率」有關。沒錯，統計學。然而這個能力在成年後將不復存在。</li><li>晝夜節律有何優勢？有利於夜間節能。那內化的晝夜節律呢？有利於提前對日照變化做出反應。</li><li>社會腦假說：新皮質的大小跟社會群體的數量呈現正相關性。由此，150 這個鄧巴數目前是硬焊在我們的生理結構中的。（補充一下，其實鄧巴數是 148）</li><li>「大腦之所以會產生意識經驗，可能是為了要幫我們認識這個世界。但弔詭的是，這些意識經驗有時候反而變成人類生活的一切。」</li><li>複雜的生物並不是比較「成功」，只是能夠適應到新的生態棲位（ecological niche），比如天空中。</li></ul>]]></content:encoded>
      
      
      <category domain="https://shuaixin.cc/categories/%E8%AE%80%E6%9B%B8%E7%AD%86%E8%A8%98/">讀書筆記</category>
      
      
      <category domain="https://shuaixin.cc/tags/%E7%94%9F%E7%89%A9/">生物</category>
      
      <category domain="https://shuaixin.cc/tags/5%E9%A1%86%E6%98%9F%E6%9B%B8%E7%B1%8D/">5顆星書籍</category>
      
      <category domain="https://shuaixin.cc/tags/%E7%94%9F%E7%90%86/">生理</category>
      
      <category domain="https://shuaixin.cc/tags/%E8%85%A6%E7%A7%91%E5%AD%B8/">腦科學</category>
      
      
      <comments>https://shuaixin.cc/Brief-History-of-Brain/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>讀書筆記：《欲望分子多巴胺》</title>
      <link>https://shuaixin.cc/The-Molecule-of-More/</link>
      <guid>https://shuaixin.cc/The-Molecule-of-More/</guid>
      <pubDate>Fri, 16 Aug 2024 16:00:00 GMT</pubDate>
      
        
        
          
          
      <description></description>
          
        
      
      
      
      <content:encoded><![CDATA[<p><img src="/The-Molecule-of-More/more.png" alt="more"></p><h3 id="多巴胺不是快樂激素，是慾望激素">多巴胺不是快樂激素，是慾望激素</h3><p>多巴胺系統被破壞的小老鼠不再主動追尋食物，但若我們親自餵他吃，他依舊會……快樂地吃。他只是不再有動力追尋快樂，但依舊能夠體驗快樂。</p><p>另一個實驗中，我們提供老鼠兩個選擇，一個是現成的普通飼料，一個是必須壓數次壓桿才會掉落的高級美食。一般情形之下，老鼠會選擇努力獲得高級美食。但多巴胺系統被破壞的那群，喪失了慾望，也就沒了動機追尋詩與遠方，於是他們自甘一輩子吃普通飼料。</p><h3 id="中樞神經中的多巴胺路徑">中樞神經中的多巴胺路徑</h3><p>書中提到了兩個多巴胺路徑。其中，<strong>中腦邊緣路徑</strong>從中腦的腹側被蓋區（下簡稱 VTA, Ventral Tegmental Area）傳到邊緣系統中的伏隔核，主司<strong>獎酬</strong>，產生欲望；而<strong>中腦皮質路徑</strong>一樣從中腦的 VTA 出發，一路延伸到前額葉皮質，主司<strong>動機</strong>，產生計算與規劃。</p><p>另外，<strong>黑質紋狀體路徑</strong>負責<strong>動作控制</strong>，若此路徑失能可能導致帕金森氏症。為什麼我要另外提這個呢？因為帕金森氏症的藥物治療方式之一就是服用左旋多巴（直接給多巴胺也過不去腦血障壁，故給前驅物），而部分患者出現的副作用是——沉迷賭博、性衝動、瘋狂購物，因為獎酬跟動機系統也一起被增強了！</p><h3 id="多巴胺跟當下分子彼此互相拮抗">多巴胺跟當下分子彼此互相拮抗</h3><p>書中將血清素、催產素、內啡肽、內源性大麻素這些令人愉悅、滿足、幸福、感到愛的腦內激素合稱為「當下分子」。雖然沒有看到他們跟多巴胺有拮抗關係的生理證據，我也查不到，但這樣理解確實在邏輯上蠻方便的。多巴胺系統讓我們高瞻遠矚、心繫未來，而當下分子則讓我們體會當下、感受快樂。</p><p>這令我不禁想到早在 1997 年就被寫下的<a href="https://shuaixin.cc/The-Power-of-Now/">《當下的力量》</a>：書中在在提醒我們，過去、未來都不是真實的，只有當下才是。我們要有意識地在「思維」（多巴胺系統）跟「臨在」（當下分子）之間切換，因為思維只關心你的未來，但只有當下才是真實的人生。</p><p>這兩本書搭在一起，醍醐灌頂！</p><h3 id="戒酒無名會與孕婦：用當下分子對抗多巴胺">戒酒無名會與孕婦：用當下分子對抗多巴胺</h3><p>還記得<a href="https://shuaixin.cc/The-Power-of-Habit/">《習慣的力量》</a>中，作者有點心虛地提到，「信任」也是維持新好習慣的重要因素。現在我們知道理由了，其實戒酒無名會透過社群的力量，灌注了人際關係之間的當下分子，進一步拮抗掉多巴胺的影響。</p><p>另一個例子是，女性在懷孕後，其戒煙率會急速飆高。這大概是催產素這個當下分子的功勞。</p><h3 id="電車問題的生理解釋：當下或未來">電車問題的生理解釋：當下或未來</h3><p>著名的電車問題至此也可以做出解釋了。當我們必須親自動手，犧牲一個無辜的路人，拯救鐵軌上的五個人，我們通常無法痛下殺手（當下分子不允許我們這麼做）。但如果我們人在遠方，在中控室裡控制鐵軌，我們就比較容易做出理性的決策，犧牲少數換取最大利益（當下分子參與較少）。更不用說如果我們是在設計自動駕駛的判斷程式了，我們一定會教程式要拯救五個人而非一個人對吧（幾乎沒有任何當下分子的活兒）。</p><h3 id="注意力不足過動症（ADHD）也跟多巴胺有關">注意力不足過動症（ADHD）也跟多巴胺有關</h3><p>目前認為，ADHD 與前述的中腦皮質路徑中多巴胺濃度不足有關。因為計算與規劃能力的缺失，ADHD 難以投入一件行動之中，容易看不見細節、聽不完說明、目標變來變去。</p><p>而目前對付 ADHD 的藥物如利他能跟安非他命，就是多巴胺再回收抑制劑。</p><h3 id="自由派與保守派">自由派與保守派</h3><p>書中對政治多有著墨，有著一整章節的討論。簡單來說，自由派是高多巴胺人格，保守派則反之。也因此，根據統計，保守派人士普遍更滿意婚姻、更容易性高潮、更少出軌。</p><p>有趣的是，我們可以透過操控恐懼（當下分子）來改變人的政治立場，而且十分容易：我們只要給予乾洗手，並提醒生活中的傳染病風險，人們就會開始偏向保守的立場。</p><h3 id="用當下分子破解最後通牒賽局">用當下分子破解最後通牒賽局</h3><p>最後通牒賽局簡單來說就是「錢怎麼分」，提案者可以任意提案，而回應者只能選擇同意或駁回，但若駁回則大家都拿不到錢，玉石俱焚。理性而言，只要有任何一點好處，回應者就應該同意。但現實中，如果提案者留給回應者的錢低於三成，回應者通常會興起「教你做人」的念頭，駁回提案。</p><p>有趣的來了，如果給回應者來一劑血清素再回收抑制劑（典型的憂鬱症藥物），當下分子濃度提高後，接受差勁提案的機率提高了一倍。</p><h3 id="多巴胺越高，移民越遠">多巴胺越高，移民越遠</h3><p>擁有較長的 DRD4 等位基因的人，會有較多的多巴胺受體。若以東非為起源來看各文化區的 DRD4，我們發現，移民越遠，DRD4 越長。</p><p>（後續查閱相關資料，DRD4 等位基因重複串聯次數較多的 7R 基因型，其受體對多巴胺的敏感度較低。導致了更多的尋奇表現與物質依賴，並可能與 ADHD 有相關性。所以應該不是簡單地越長越多受體。）</p><p>另外，雙相障礙（俗稱躁鬱症）患者有多巴胺再回收的問題，在躁期會有太高的多巴胺濃度。有趣的來了，移民國家代表美國的躁鬱症比例是全世界最高，而對比的非移民國家代表日本則是全世界最低。</p><p>若問「人生中的成就是否由我們無法控制的力量所決定？」，歐洲國家平均給出了五成以上的肯定答案，但美國只有不到三分之一——高多巴胺風格的回答。</p><h3 id="性質特殊的尼古丁">性質特殊的尼古丁</h3><p>尼古丁是一個特別的成癮性物質，它不會讓人爽，但卻依舊會上癮。所以攝取尼古丁的唯一作用就是——讓你暫時不想再來一發尼古丁。</p><p>書中打趣地說，抽煙唯一的意義就是上癮，煙癮者就像刻意背起一塊大石頭，然後體驗放下石頭時的神清氣爽 XD</p><h3 id="追尋幸福的人反而更不幸福">追尋幸福的人反而更不幸福</h3><p>此書讀畢後，碰巧聽了一集關於「幸福」的 Podcast（<a href="https://hiddenbrain.org/podcast/happiness-2-0-the-path-to-contentment/">Happiness 2.0: The Path to Contentment</a> ），其中有幾個 Point 如下：</p><ul><li>越是看重幸福的人，其幸福程度越低</li><li>越是認為自己正在努力追求幸福的人，其幸福程度越低</li><li>越是想擺脫負面情緒的人，其幸福程度越低</li><li>以上主要是針對美國人的發現</li><li>進一步研究了重視社群的亞洲國家，包含台灣、日本，發現了相反的情形：若是認為幸福跟人際連接有較大關聯（相對於美國比較認為幸福是個人追求），那麼此時越是看重「幸福」，其幸福程度跟剛剛相反，是更高</li></ul><p>是不是與本書頗有相關之處？</p><p>看重幸福與追尋幸福都是高多巴胺的風格，於是這群人著眼未來，往未來邁進的同時，犧牲了享受當下的機會。</p><p>那麼為何重視人際連結的亞洲國家卻相反呢？因為人際連結是「當下分子」的活兒啊！</p><h3 id="Other-Good-Points">Other Good Points</h3><ul><li>多巴胺也會提高自我效能（self-efficacy）。故可卡因（血清素、多巴胺再回收抑制劑）跟安非他命（多巴胺再回收抑制劑）的吸食者會有無所不能的自信心爆棚感。</li><li>一日之計最難的地方，就是每天醒來，我都在改進世界與享受人生之間躊躇——E. B. White（《夏綠蒂的網》作者）<ul><li>I arise in the morning torn between a desire to improve the world and a desire to enjoy the world. This makes it hard to plan the day.</li></ul></li><li>自由派與無神論者的平均智商較高：人類的平均智商是 100 分，極端自由派的智商是 106，而極端保守派則是 95。而宗教信仰和智商也有類似的關聯，但相似度沒那麼高。無神論者的平均智商為 103，而自認信仰非常虔誠的人平均智商只有 93。</li></ul>]]></content:encoded>
      
      
      <category domain="https://shuaixin.cc/categories/%E8%AE%80%E6%9B%B8%E7%AD%86%E8%A8%98/">讀書筆記</category>
      
      
      <category domain="https://shuaixin.cc/tags/5%E9%A1%86%E6%98%9F%E6%9B%B8%E7%B1%8D/">5顆星書籍</category>
      
      <category domain="https://shuaixin.cc/tags/%E7%94%9F%E7%90%86/">生理</category>
      
      <category domain="https://shuaixin.cc/tags/%E8%85%A6%E7%A7%91%E5%AD%B8/">腦科學</category>
      
      
      <comments>https://shuaixin.cc/The-Molecule-of-More/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>智能家居 EP6：設定自動化</title>
      <link>https://shuaixin.cc/HA-6-Automation/</link>
      <guid>https://shuaixin.cc/HA-6-Automation/</guid>
      <pubDate>Sun, 04 Aug 2024 16:00:00 GMT</pubDate>
      
        
        
          
          
      <description></description>
          
        
      
      
      
      <content:encoded><![CDATA[<p>上一篇我們把無線開關納入 HA 版圖了，但這些開關目前還沒有任何的控制功能。我們這邊就要來透過自動化，去指定開關對應到的動作。</p><h3 id="設定自動化">設定自動化</h3><p>側邊欄「設定」→「自動化與場景」→ 右下角「新增自動化」：</p><p><img src="/HA-6-Automation/HA-auto.jpg" alt="HA-auto"></p><p>我們在「新增一個觸發」中選擇「裝置」，並選擇到我們的無線開關。以我這邊為例，我選擇了塗鴉開關（而這個開關就黏在我的電腦桌正下方，我手可以直接摸下去操作）：</p><p><img src="/HA-6-Automation/HA-add-auto.jpg" alt="HA-add-auto"></p><p>無線開關最基本的觸發方式不外乎就是「單擊」跟「雙擊」，我們可以分別指定做不同的用途，而我這邊則是設定「單擊」就幫我「切換」燈。</p><p>這邊注意我們不太會設定成「開啟」或是「關閉」，畢竟開關有不同的操作方式也是蠻奇怪的對吧：</p><p><img src="/HA-6-Automation/HA-auto-do.jpg" alt="HA-auto-do"></p><p>如此，我的這個工作燈不僅可以透過 HA 控制、從家庭 App 控制、喊 siri 控制，現在還有一個實體的無線按鈕可以控制了。</p><p>接著我指定同一個開關的「雙擊」控制我的小米插座：</p><p><img src="/HA-6-Automation/HA-Mi.jpg" alt="HA-Mi"></p><p>而我的插座接的是書櫃的燈條，作為氣氛燈。當然，你可以接上任何你想接的設備。</p><p>好了，我們下篇見 :)</p>]]></content:encoded>
      
      
      <category domain="https://shuaixin.cc/categories/%E6%99%BA%E8%83%BD%E5%AE%B6%E5%B1%85/">智能家居</category>
      
      
      <category domain="https://shuaixin.cc/tags/Home-Assistant/">Home Assistant</category>
      
      
      <comments>https://shuaixin.cc/HA-6-Automation/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>智能家居 EP5：Zigbee 設備參戰</title>
      <link>https://shuaixin.cc/HA-5-Zigbee/</link>
      <guid>https://shuaixin.cc/HA-5-Zigbee/</guid>
      <pubDate>Sat, 03 Aug 2024 16:00:00 GMT</pubDate>
      
        
        
          
          
      <description></description>
          
        
      
      
      
      <content:encoded><![CDATA[<p>ok 來捋一下現在的進度：</p><p>現在我們有一台 HA 伺服器，拿到了米家設備的掌控權，並且把這些掌控權進一步橋接給了 Apple Home。</p><p>所以我們目前已經可以透過「HA 的網頁」、「Siri」跟「家庭 App」來控制設備了。</p><p>但是這樣少了一個很重要的控制方式——實體開關！如果每次都要拿起手機來操作或用喊的，其實不見得方便對吧？所以我們這篇要來加入 Zigbee 實體開關。</p><p><img src="/HA-5-Zigbee/mqtt_ha.png" alt="mqtt_ha"></p><h3 id="硬體需求">硬體需求</h3><p>這部分我們會需要支援 Zigbee 的設備，而我們用的方案是來自開源社群的 Zigbee2MQTT，所以可以到<a href="https://www.zigbee2mqtt.io/supported-devices/">支援設備</a>挑挑看選選看（超多的！）。我們此篇以<a href="https://www.zigbee2mqtt.io/devices/IH-K663.html">塗鴉無線開關</a>跟<a href="https://www.zigbee2mqtt.io/devices/WXKG01LM.html#xiaomi-wxkg01lm">小米無線開關</a>為例，因為我們急需實體開關嘛。</p><p>再來我們會需要一個直接插在 HA 伺服器上的 Zigbee 協調器，我自己是用 <a href="https://sonoff.tech/product/gateway-and-sensors/sonoff-zigbee-3-0-usb-dongle-plus-p/">SONOFF Zigbee 3.0 USB Dongle Plus-P</a>，大家可以根據<a href="https://www.zigbee2mqtt.io/guide/adapters/">支援的協調器</a>做選擇。</p><h3 id="安裝-Mosquitto-Broker">安裝 Mosquitto Broker</h3><p>附加元件（都 EP5 了我就不慢慢帶咯）搜尋並安裝 Mosquitto Broker，並直接啟用：</p><p><img src="/HA-5-Zigbee/HA-mosquitto.jpg" alt="HA-mosquitto"></p><p>這步驟就完成了。</p><p>啊這是做什麼用的？MQTT 是一種設備之間的溝通協議，我們等等的 Zigbee 設備的互相交流都要通過這個協議，所以理當我們的伺服器也要先裝好 MQTT 的溝通原則咯。</p><h3 id="安裝-Zigbee2MQTT">安裝 Zigbee2MQTT</h3><p>側邊欄「設定」→「附加元件」→ 右上角三點「儲存機制」：</p><p>我們新增一個儲存庫進去：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">https://github.com/zigbee2mqtt/hassio-zigbee2mqtt</span><br></pre></td></tr></table></figure><p><img src="/HA-5-Zigbee/HA-addurl.jpg" alt="HA-addurl"></p><p>如此一來，我們的附加元件商店就能找到我們要的 Zigbee2MQTT 咯：</p><p><img src="/HA-5-Zigbee/HA-zigbee2.jpg" alt="HA-zigbee2"></p><p>我們安裝它，但不用啟動。</p><p>我們先到「設定」→「系統」→「硬體」→「所有硬體」裡面找我們的協調器：</p><p><img src="/HA-5-Zigbee/HA-address.jpg" alt="HA-address"></p><p>以我們這邊為例就是 ttyUSB0。</p><p>接著我們回到附加元件，進去 Zigbee2MQTT 的設定處。其中我們只更改 mqtt 跟 serial 兩處。</p><p>mqtt 填入：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">server: mqtt://core-mosquitto</span><br><span class="line">user: 你的HA用戶名</span><br><span class="line">password: 你的HA密碼</span><br></pre></td></tr></table></figure><p>serial 填入：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">port: /dev/剛剛硬體那邊看到的位置</span><br></pre></td></tr></table></figure><p><img src="/HA-5-Zigbee/HA-zigbee2setting.png" alt="HA-zigbee2setting"></p><p>儲存後，啟動 Zigbee2MQTT。</p><h3 id="加入-Zigbee-設備">加入 Zigbee 設備</h3><p>成功開啟後，我們就能看到空空的裝置清單了：</p><p><img src="/HA-5-Zigbee/HA-zig2.jpg" alt="HA-zig2"></p><p>點擊「允許裝置加入」，開始拿起你的設備進行連接吧！以這邊為例，塗鴉開關只要長按五秒，但小米開關要拆開來插洞洞，有夠麻煩的啦（而且每次都要翻找我的退卡針）。</p><p>加入完成：</p><p><img src="/HA-5-Zigbee/HA-zigdevice.jpg" alt="HA-zigdevice"></p><p>可以從線路圖裡看到各個設備的連接關係：</p><p><img src="/HA-5-Zigbee/HA-route.png" alt="HA-route"></p><p>Very good！開關成功參戰，我們下一篇就來讓開關控制我們的設備吧 :)</p><hr><p>補一個後來更熱鬧後的拓撲：</p><p><img src="/HA-5-Zigbee/image-20250606135650379.png" alt="image-20250606135650379"></p><p>可以看到，Zigbee 的一個好處就是，當有人發現訊號不太穩定時，會自動去找更近的 router 來連線。</p>]]></content:encoded>
      
      
      <category domain="https://shuaixin.cc/categories/%E6%99%BA%E8%83%BD%E5%AE%B6%E5%B1%85/">智能家居</category>
      
      
      <category domain="https://shuaixin.cc/tags/Home-Assistant/">Home Assistant</category>
      
      
      <comments>https://shuaixin.cc/HA-5-Zigbee/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>智能家居 EP4：給 Siri 控制權！</title>
      <link>https://shuaixin.cc/HA-4-HomeKit/</link>
      <guid>https://shuaixin.cc/HA-4-HomeKit/</guid>
      <pubDate>Fri, 02 Aug 2024 16:00:00 GMT</pubDate>
      
        
        
          
          
      <description></description>
          
        
      
      
      
      <content:encoded><![CDATA[<p>目前為止，我們已經把一些基礎設備加進 HA。</p><p>現在我們要把這些設備進一步導入到 Apple Home 裡面，如此一來我們家 Siri 就可以控制這些設備了！</p><h3 id="安裝-HomeKit-Bridge">安裝 HomeKit Bridge</h3><p>這部分就沒有 HACS 的戲份了，因為 HA 官方有提供這個功能。</p><p>其中的邏輯就是，我們讓我們的 HA OS 伺服器充當橋接器，把 HA 連接到的所有設備導入到 Apple Home 裡面。</p><p>從側邊欄「設定」→「裝置與服務」→ 右下角「新增整合」→ 搜尋 homekit 並選擇「HomeKit Bridge」：</p><p><img src="/HA-4-HomeKit/HA-homekit.jpg" alt="HA-homekit"></p><p>按照引導安裝即可。</p><p>接著，我們會發現側邊欄「通知提示」跳了新通知，點進去會發現它幫我們生成了橋接器的 QR code：</p><p><img src="/HA-4-HomeKit/HA-bridgeQR.jpg" alt="HA-bridgeQR"></p><p>此時拿起你的 ios 設備，打開你的家庭 app，透過掃描加入配件：</p><p><img src="/HA-4-HomeKit/HA-add.png" alt="HA-add"></p><p>成功後，Home 會把橋接器連接的所有設備一個一個讓你導入家中，如果你有很多設備的話，會花一陣子，耐心！</p><p>設定完成後，設備就都進來咯：</p><p><img src="/HA-4-HomeKit/HA-homekit.png" alt="HA-homekit"></p><p>此時就可以透過 Siri 操控設備咯！</p>]]></content:encoded>
      
      
      <category domain="https://shuaixin.cc/categories/%E6%99%BA%E8%83%BD%E5%AE%B6%E5%B1%85/">智能家居</category>
      
      
      <category domain="https://shuaixin.cc/tags/Home-Assistant/">Home Assistant</category>
      
      
      <comments>https://shuaixin.cc/HA-4-HomeKit/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>智能家居 EP3：將小米裝置加入 HA</title>
      <link>https://shuaixin.cc/HA-3-miot/</link>
      <guid>https://shuaixin.cc/HA-3-miot/</guid>
      <pubDate>Thu, 01 Aug 2024 16:00:00 GMT</pubDate>
      
        
        
          
          
      <description></description>
          
        
      
      
      
      <content:encoded><![CDATA[<blockquote><p>如果你手上沒有小米設備可以跳過此篇，先去 EP5 添加 Zigbee 設備是個不錯的開始</p></blockquote><h3 id="安裝-Xiaomi-Miot">安裝 Xiaomi Miot</h3><p>我們上篇已經弄出了 HACS，現在我們就要來發揮它的妙用啦！</p><p>在 HACS 中找到「Xiaomi Miot Auto」，把它下載下來：</p><p><img src="/HA-3-miot/HA-hacs-miot.jpg" alt="HA-hacs-miot"></p><p>接著到側邊欄「設定」→「裝置與服務」→ 右下角「新增整合」→ 找到我們剛剛下載下來的「Xiaomi Miot Auto」：</p><p><img src="/HA-3-miot/HA-miot.jpg" alt="HA-miot"></p><p>開始根據引導安裝。有特別需求的可採取局域網集成，但各位已經在用米家智能產品的用戶應該都有帳號，不妨直接透過帳號導入即可：</p><p><img src="/HA-3-miot/HA-mi-account.jpg" alt="HA-mi-account"></p><p>如此一來，你米家的設備就自動導入 HA 咯：</p><p><img src="/HA-3-miot/HA-mi.jpeg" alt="HA-mi"></p><p><img src="/HA-3-miot/Mi-inha.jpg" alt="Mi"></p><p>如此一來我們就能從 HA 控制我們的米家設備了！</p><h3 id="後續新增小米裝置">後續新增小米裝置</h3><p>此例中，我又多買了一個米家智慧空氣循環扇，我們來一起添加它。</p><p>首先當然是將設備先按照官方正常方法接入米家 app，接下來我們才能在 HA 中找到它。</p><p>接入米家後，我們到「裝置與服務」的「整合」中找到 Xiaomi Miot Auto。</p><p><img src="/HA-3-miot/Miot1.png" alt="Miot1"></p><p>進去後選擇新增條目：</p><p><img src="/HA-3-miot/Miot4.png" alt="Miot4"></p><p>這裡因為我們只要單獨新增一個設備，所以選擇 include：</p><p><img src="/HA-3-miot/Miot5.png" alt="Miot5"></p><p>找到我們的設備：</p><p><img src="/HA-3-miot/Miot6.png" alt="Miot6"></p><p>添加後若沒有看到生效，可以重開機中選擇快速重載。</p><p>大功告成！</p><hr><p>下一步我們要進一步將控制權交給 siri，我們下篇見 :)</p>]]></content:encoded>
      
      
      <category domain="https://shuaixin.cc/categories/%E6%99%BA%E8%83%BD%E5%AE%B6%E5%B1%85/">智能家居</category>
      
      
      <category domain="https://shuaixin.cc/tags/Home-Assistant/">Home Assistant</category>
      
      
      <comments>https://shuaixin.cc/HA-3-miot/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>智能家居 EP2：安裝 HACS</title>
      <link>https://shuaixin.cc/HA-2-HACS/</link>
      <guid>https://shuaixin.cc/HA-2-HACS/</guid>
      <pubDate>Wed, 31 Jul 2024 16:00:00 GMT</pubDate>
      
        
        
          
          
      <description></description>
          
        
      
      
      
      <content:encoded><![CDATA[<h3 id="為何安裝-HACS">為何安裝 HACS</h3><p>HACS 全名 Home Assistant Community Store，沒錯，社群的力量無限大。</p><p>為了後續我們要把米家裝置連進 HA、Zigbee 連進 HA、裝置們橋接進 Apple Home，我們就要依靠這個 HACS 裡面社群們開發的插件。</p><p>另外，HACS 的安裝流程中會需要 github 帳號，還請先準備好。</p><h3 id="安裝-Terminal-SSH">安裝 Terminal &amp; SSH</h3><p>在安裝 HACS 前，我們要先安裝 Terminal &amp; SSH。</p><p>進入附加元件商店：</p><p><img src="/HA-2-HACS/HA-store.jpg" alt="HAstore"></p><p>搜尋 SSH，然後你會發現沒有我們要的元件，所以我們要開啟進階模式：</p><p><img src="/HA-2-HACS/HA-advanced-mode.jpg" alt="HAadvance"></p><p>開啟後就找得到了，咱們安裝它：</p><p><img src="/HA-2-HACS/HA-SSH.jpg" alt="HAssh"></p><p>安裝完畢後開啟，可以看到如下畫面：</p><p><img src="/HA-2-HACS/HA-ssh-1.jpg" alt="HAssh1"></p><p>實際上這個畫面呢，你如果把伺服器連一個螢幕出來，也是同一個畫面哦！</p><p>聰明的你可能發現了，如果我們給伺服器來一套鍵盤跟顯示器，我們這步 Terminal &amp; SSH 的安裝其實可以跳過啦。</p><h3 id="安裝-HACS">安裝 HACS</h3><p>好了，現在我們可以直接對伺服器下指令了。</p><p>我們此時輸入：</p><blockquote><p>wget -O - <a href="https://get.hacs.xyz">https://get.hacs.xyz</a> | bash -</p></blockquote><p>並 enter 執行，就會將 HACS 下載下來咯：</p><p><img src="/HA-2-HACS/HA-bash.jpg" alt="HA-bash"></p><p>至此，我們重啟一次整個 HA 系統。</p><p>接著進入側邊欄的「設定」→ 「裝置與服務」→ 右下角「新增整合」，搜尋 HACS，開始安裝它：</p><p><img src="/HA-2-HACS/HA-hacs.jpg" alt="HA-hacs"></p><p>安裝過程中，會需要 github 帳號授權，此為正常現象，跟著走完吧。</p><p>安裝成功後，你的側邊欄就會出現 HACS 的 icon 咯：</p><p><img src="/HA-2-HACS/HA-hacs-icon.png" alt="HA-hacs-icon"></p><p>幹得漂亮，我們下篇見 :)</p>]]></content:encoded>
      
      
      <category domain="https://shuaixin.cc/categories/%E6%99%BA%E8%83%BD%E5%AE%B6%E5%B1%85/">智能家居</category>
      
      
      <category domain="https://shuaixin.cc/tags/Home-Assistant/">Home Assistant</category>
      
      
      <comments>https://shuaixin.cc/HA-2-HACS/#disqus_thread</comments>
      
    </item>
    
  </channel>
</rss>
