ArozOS 的桌面大更新
之前有一段時間我都在想幫 ArozOS 的桌面做一個大更新,把最頂部的仿 Ubuntu 狀態欄拿掉,可是因為開刀和學業上各種事情一直沒空完成。最近新年前剛好指導教授不在一個禮拜,所以我就來更新了一下這個久久沒時間完成的小目標。 原先 web-desktop 的界面,上下都有一個黑色的功能欄 新的 web-desktop 界面,最頂部實色的被整合到下方的欄內 日曆和通知也被移到右下方 右下方角落的那個圈圈就是以前在右上方的背景執行工作列表 其中我最喜歡的功能大概就是這個系統一覽表了。從伺服器的在線狀態,名稱,SMART 狀態到各顆硬碟的使用量都能夠直接看清楚。 嘛當然除了這個以外還加入了很多微細的使用者體驗最佳化,例如說背景加深 + 模糊的狀態來突顯某個元件之類的 未打開日曆前的背景 打開日曆後加入的 backdrop-filter blur,突出了日曆和通知欄的前置感 另外也加入了能直接進入進階分享設定的功能按鈕,比起以往要進入到 File Manager 來更改進階設定要來得更方便。 這樣的界面大概已經算得上是追到近年的 web-desktop 界面水平了吧?雖然說在 github web-desktop 的分類排行中 ArozOS 是掉到了第四位,但是以完整性來說 ArozOS 還是跟 DSM 比得上的 web-desktop 類界面(
Golang – 加速抓資料夾的總大小的方法
最近因為一些意外所以要頻繁跑醫院回診,結果就是在等待跟來回的時間前後多了很多零碎的時間,所以我就不浪費這些時間來幫我用了快 6 - 7 年的 ArozOS 系統做了點更新了。但是這篇部落格並不是在講我更新了甚麼(雖然某程度上也是),而是講一下關於 Golang 處理 exec 輸出的一個小發現。 背景故事 - ArozOS 的 Disk Properties 載很慢 ArozOS 的 Disk Properties ArozOS 因為採用半虛擬磁碟架構的設計,所以每次要列出 disk space 的時候,除了一般像 Windows 那樣會列出用了多少跟全部空間是多少以外,如果磁碟空間是使用者分隔的,就要多計算使用者佔用的空間比(圖上黃色條) 這個功能原本是使用 Walk function 來實現的。因為 ArozOS 的 vfs architecture 關系,這裡我使用的是 ArozOS 專用的 filepath module (你可以把它想像成 Go 原本的 filepath.Walk var size int64 = 0 fshAbs.Walk(rpath, func(_ string, info os.FileInfo, err error) error { if err != nil { return err } if !info.IsDir() { size += info.Size() } return err }) filesize = size fshAbs 是 file system handler abstraction 的意思,大概就是「這個虛擬磁碟的檔案系統層」的 object。 另外 rpath 就是從 user space translate 過來到這個 abstraction layer 的實質路徑,如果是本機磁碟的話就會是好像 /media/storage1/users/{username}/myfile.txt 這樣的 path;如果是 network drive 的話會是跟 mount-point 的相對路徑,例如 WebDAV 或是 FTP 下就可能會出現 /myfile.txt,或是 SMB 下的 /Share/myfile.txt 之類。 這樣的 implementation 你一看就可以知道這個在 Network Drive 上是不可能實現的,因為每一個檔案 Go 都要抓它的 Stat,即是遠端有多少個檔案就會送多少個 file request 過去,所以自很早之前就 ArozOS 的 File Manager 就加入了 這個簡單粗暴的解決方法… if fsh.IsNetworkDrive() { filesize = -1 } 然而隨著我在用的 NAS 東西越來越多,這個 walk function 即使在 local disk 下也開始變得很慢。 那改用 kernel 內置的 API 來抓不就好了嗎? 確實如此。Linux kernel 裡其實有內置一個滿好用的指令叫 du,用起來也超簡單,只要: du -sb /media/storage1 481491222874 /media/storage1 那這個資料夾總大小(byte size)就出來了。如果你想要 block size 的話可以把 b 去掉。然後就是寫一個簡單的 Go function 去把資料抓出來。 /* Get Directory Size with native…
ArozOS 的多帳號切換系統原理
講到多帳戶切換系統,通常你只會在一些類似 AWS 或者 Google 那樣大規模的系統裡面才會看到,然而這並不是沒有原因的。因為有時候部分功能為了權限上的分別,不少人比起想要設定一個擁有多權限群組的用戶,反而會比較喜歡以帳戶的方式來使用不同權限群組的作業環境。 早在好幾十個版本之前,ArozOS 就可以建立不同的權限群組而且讓一個用戶加入不同的群組 單用戶多權限群組設計 原先的 ArozOS 採用多用戶多權限群組的設計,簡單來說就是每個用戶都可以加入一個或以上的權限群組,而這個用戶能做的事情和存取的儲存裝置就是 UNION of 所有的權限群組。假設群組 A 只能存取 A 的儲存池,群組 B 只能存取 B 的儲存池,那一個用戶加入了 A 和 B 的群組之後便能存取 A 和 B 兩個儲存池的資料,並在此中間自由移動和開啟檔案。 然而,不知道是不是這設計對於現代人來說太複雜了,很多人就是不會用,然後問我到底要怎樣才可以建立更多自用的使用者帳戶。建立之後他們又會來問到底要怎樣才可以把檔案在用戶之間移動,我就一整個(嗯??? 多用戶單權限群組設計 所以後來我在跟用戶訪談的時候,發現其實他們比較多在用多用戶單群組的用法。簡單來說,就是一個用戶只有一個權限群組,當他們想要存取另一個權限群組的資料的時候,他們便會登出原先帳戶並登入另一個帳戶。這用法通常是用來處理一些對外的服務(例如 www 的帳號來處理跟 web service 相關的檔案),但是用在 cloud desktop 上的這種要求我猜我應該是第一個 implement 的說? 所以為了體驗這種奇怪的使用方法,我特別在 test bench 上架了一個網站,讓 www 帳戶來保存檔案。 在 www 上架的一個 html file 然後就開始設計帳戶切換的邏輯。首先,一般的帳戶切換做法是使用 client side cookie / session 對每個帳戶進行登入,然後讓用戶可以自由切換在該 browser 上任何未過期的 login session。然而,在 ArozOS 上這有點不太可行 ArozOS 的 authentication 是基於 cookie 而非 localStorage。如果設計改了的話對一些依賴 legacy login API 的系統會帶來嚴重問題ArozOS 是網頁桌面系統,相比起其他網頁的 stateless 設計,ArozOS 的桌面是 stateful 的,而且整個狀態是儲存在伺服器端部分用戶在 ArozOS 上使用 oAuth / LDAP 作為登入認證伺服器,加上之後有打算加入 Cluster Authentication System 等伺服器端較複雜的結構,在客戶端上儲存登入狀態可能比較難做到跨伺服器間的 user state transfer 所以結合上述原因,我們最後採用了一個叫 Switchable Accounts Pool 的設計。 Switchable Accounts Pool (SAP) 是一個我們設計出來的實驗性東西。它的功能大概就是以一個 pool id 來對應一堆可以切換的帳戶,而這些帳戶又會有 main / secondary 的關系,讓帳戶的登出的時候在伺服器端對該瀏覽器的登入狀態進行切換。 一開始,當主帳戶登入的時候,一個在伺服器端的 SAP 便會被建立。Creator 的名字就會寫著是主帳戶的名字。之後,用戶可以透過登入 sub-account 以取得在這個 session 結束之前,可以不斷切換到 sub-account 的權利。 當 Sub account 登出的時候,由於 main account 的 session 仍存在,因此伺服器端會直接改寫 User 的 login cookie 到原先的 creator account。 而當 Main account (即 SAP 的 Creator)登出的時候,伺服器端便會直接 discard 整個 SAP 以保護其他 sub-account 的安全(非法透過登入 sub-account 以取得 main account 的存取權)。 在邏輯搞清楚之後,剩下的便是把功能寫出來了。這裡只是一點簡單的 Go programming,技術上沒甚麼特別的所以我就不再詳談。 網頁桌面上的可切換帳戶 新增帳戶的時候需要使用密碼登入,如果是近來切換過的而 session 沒過期可以透過伺服器端免密碼切換 在一些特殊情況下,例如說 main account 的 login session expire 但是 SAP 的 session 還沒 expire ,使用者便會在登入界面看到這樣的一個 popup,讓他可以快速回復之前登入過的…
ArozOS 的相容性存取模式
在開發 ArozOS 這個計劃的時候,其實大部分的時間我都不是用來寫功能性的東西,而是開發前端,以提升使用者體驗(UX)的東西。從網頁桌面到簡單易用的設定與管理系統,從 FTP 到 WEBDAV 接口等,都是讓不同的用戶及自己能在不同的裝置與環境下使用到自己的伺服器。然而自從 1.0 版 ArozOS 開始開發之後我們一直都還沒有放進去的,就是相容模式了。 新版的硬碟掛載界面 新版的檔案伺服器界面 從 Aroz Online Beta 起相容模式就一直是我們堅持的功能之一。其一是為了一些極端的使用裝置(例如 DSi 的瀏覽器、快譯通之類的嵌入式裝置)可以使用 ArozOS 為資料傳輸用之外,也可以用在一些很惡劣的網絡環境下,讓相容模式變成遠端使用 ArozOS 的最終手段。 AOB 下的相容登入模式 相容模式下只能勉強執行一些簡單的 WebApp 可是 AOB 的相容模式下真的沒辦法做甚麼,除了 Music 跟 Setting 幾個 WebApp 之外幾乎甚麼都沒辦法做(特別是連 File Manager 都開不了這點最讓我覺得奇怪),所以我猜當時開發相容模式就只是為了可以產生伺服器端的 session 然後用同一組 session 來存取伺服器上其他的服務而已。 ArozOS 2.0 的 相容模式 ArozOS 2.0 新加入的 Directory Server 相容存取模式 去到 ArozOS 2.0 之後,相容模式的登入界面也被直接改成有一定年代歷史的 Basic Auth 處理,也把界面盡量減少到只使用最基本的 HTML5 及顯示最基本的虛擬檔案系統層 ArozOS 2.0 的 file system abstraction ,以 compatibility mode 顯示 這樣的設計不但能相容最多的裝置,作業系統等,也能在極為惡劣的網絡環境下(Kbps 速度)存取到你放在伺服器的資料,對於在緊急需要下載個文件之類的還是有點用途(我猜) 如果你有一定年紀的話你會發現這界面好像在哪裡看過。沒錯,這是參考 Apache 的 list dir 界面設計的。簡單、直接的設計怎樣說還是參考前人設計為佳。 Apache 預設的 list dir 界面 結論:實用性有時候比技術重要 現在的前端都太複雜了,不是依靠 Virtual DOM 就是依賴一大堆 HTML5 attribute tags。有時候當你開發的系統是以實用性和高相容性為主的時候,不妨考慮一下以機能而非技術先行,採用 server side 直出 HTML 的做法還比較實際。
在 Raspberry Pi Zero 2W 上設定 WiFi AP 作為 WiFi 中繼器
因為不知道為甚麼網上沒有 Raspberry Pi Zero 2W 以外接 WiFi USB 作為 WiFi 中繼器的教學,所以我就來自己研究出一個方法囉 材料 Raspberry Pi Zero 2WRaspberry Pi OS 用作 wlan1 的 USB WiFi 模組 安裝所需 Package sudo apt-get update sudo apt-get upgrade sudo apt-get install hostapd sudo apt-get install dnsmasq sudo systemctl stop hostapd sudo systemctl stop dnsmasq 設定網絡界面卡 sudo mv /etc/dnsmasq.conf /etc/dnsmasq.conf.orig sudo nano /etc/dnsmasq.conf 寫入以下內容 interface=wlan1 dhcp-range=192.168.0.11,192.168.0.30,255.255.255.0,24h 固定 wlan1 的 IP 地址 sudo nano /etc/network/interfaces 把 source /etc/network/interfaces.d/* 加上 comment: #source /etc/network/interfaces.d/* 寫入以下內容 auto lo iface lo inet loopback auto wlan0 iface wlan0 inet dhcp allow-hotplug wlan1 iface wlan1 inet static address 192.168.0.10 netmask 255.255.255.0 broadcast 192.168.0.255 gateway 192.168.0.254 設定 Hostapd sudo nano /etc/hostapd/hostapd.conf 寫入以下內容(記得更新 WiFi 名稱與密碼) interface=wlan1 hw_mode=g channel=7 wmm_enabled=0 macaddr_acl=0 auth_algs=1 ignore_broadcast_ssid=0 wpa=2 wpa_key_mgmt=WPA-PSK wpa_pairwise=TKIP rsn_pairwise=CCMP ssid=[WiFi SSID 名稱] wpa_passphrase=[WIFI 密碼] 之後編輯預設設定 sudo nano /etc/default/hostapd 把原本的 #DAEMON_CONF="" 改成 DAEMON_CONF="/etc/hostapd/hostapd.conf" 設定 wlan1 -> wlan0 的 forwarding sudo nano /etc/sysctl.conf 把 #net.ipv4.ip_forward=1 改成 net.ipv4.ip_forward=1 新增 iptables 規則 如果你是用 Lite 版沒有 iptables 可以先透過以下指令安裝 sudo apt-get install iptables 然後輸入 sudo iptables -t nat -A POSTROUTING -o wlan1 -j MASQUERADE sudo sh -c "iptables-save > /etc/iptables.ipv4.nat" 編輯 rc.local 在啟動時自動應用規則 sudo nano…
使用 Apache2 當 Reverse Proxy 伺服器
因為最近房東在沒經我同意之前在房間的網絡上遊加入了一台 NAT 路由器,所以原本架在我的房間裡的 ArozOS 伺服器就沒辦法在外面連線了。想了想,於是我想到了可以透過 zeroTier 和 Reverse Proxy 來使用我房間裡的伺服器,所以便開始研究怎樣可以弄到一台 Reverse Proxy 的伺服器。 網絡上很多人喜歡用 nginx 來當 RP伺服器,可是基於某些原因我並沒有太喜歡它所以我就選擇用 Apache2 了。首先,安裝 apache2 sudo apt-get update sudo apt-get install apache2 -y 然後就是編輯它的設定檔,加入你需要 proxy 的目標 sudo nano /etc/apache2/sites-available/000-default.conf NameVirtualHost *:80 <VirtualHost *:80> ServerName ixtw.hkwtc.com ProxyPass / http://{zerotier 的區網 ip}:8080/ ProxyPassReverse / http://{zerotier 的區網 ip}:8080/ </VirtualHost> <VirtualHost *:80> DocumentRoot /var/www/html </VirtualHost> 然後 Enable Proxy 插件並重啟 apache 2 sudo a2enmod proxy_http sudo systemctl restart apache2 可是,WebSocket 要求過不去欸? 這是因為要 proxy websocket 會需要額外的 module 去處理,首先啟用 wstunnel 跟 rewrite engine sudo a2enmod proxy_wstunnel sudo a2enmod rewrite sudo systemctl restart apache2 然後加入 RewriteCond 跟 RewriteRule <VirtualHost *:80> ServerName ixtw.hkwtc.org RewriteEngine On RewriteCond %{HTTP:UPGRADE} ^WebSocket$ [NC,OR] RewriteCond %{HTTP:CONNECTION} ^Upgrade$ [NC] RewriteRule /(.*) ws://192.168.196.15:8082/$1 [P,QSA,L] ProxyPass / http://192.168.196.15:8082/ ProxyPassReverse / http://192.168.196.15:8082/ </VirtualHost> 最後再重啟一次 apache sudo systemctl restart apache2 這樣就完成了!
ArOZ Portable 主板開發計劃
說到 ArOZ Portable 計劃,這是一台可以放進口袋裡的迷你 ArozOS 伺服器。如果你沒看過的話現在的版本大約長這樣 最穩定版本的設計 可是如果你有機會把它拆開來看,你就會發現這版本其實是沒辦法量產的。因為裡面的線路長這樣 所以結論是:在真的量產之前我要先把它變成可以量產的設計。 ArOZ Portable 主板 通常說到電腦、手提電子裝置等等的東西第一個最基本的東西就是主板了。 這個計劃由 2016 年開始我就不斷在嘗試弄一塊主板來省略那堆亂七八糟的走線,可是每次都因為不同的原因而失敗。最大的原因可能是因為我還沒有焊接 小於 SOP 跟 0805 針腳的技術力吧,也有不少原因是當年的畫板技術還沒足夠讓我真的去自由發揮。 在這裡我就跟大家分享一下這幾年來我設計的 ArOZ Portable 主板(失敗品)吧 初代 ArOZ Portable 主板 第一代的 ArOZ Portable 主板 這一塊主板基本上就是一塊 FE1.1S USB Hub 晶片 + Micro SD 轉 USB 的晶片(用以代替外接的 USB 儲存裝置),但是當然這兩塊晶片的腳位都是 SSOP 的,而到現在我還是沒有合適的工具去焊接 SSOP 腳位,所以這板子當然是失敗了。 第二代主板 第二代的主板主要是把 SD 卡讀卡器移除,跟把充電電路放回進去。你在 U2 的位置能夠看到一個熟悉的 TP4056 layout,理論上是可以提供 5V 1A 的充電性能。但是唯一一個問題是這電路設計的時候沒考慮到 5V 升壓問題(而且還要畫完,在掉去生產前一刻才發現這問題),而大部分 USB 裝置必須要有 5V 供電才能運作,結果這板子也是不能用的。 第三代主板 在發現第二代這種低級錯誤之後第三代就換回去用移充的主板來供電了(右上的那個凹進去的位置),然後順便加粗了供電的走線和買了焊膏和熱風槍。雖然有成功焊出一兩塊,但是最後也是因為 FE1.1S 焊的良率太低而報廢(果然還是需要紅外線焗爐啊) 第四代 想著既然第三代都能有幾個 % 的成功率,那第四代也能碰碰運氣看看定 20塊板子有沒有一塊能成功吧?於是我把充電、升壓、USB Hub 等等全部放到一塊板子上面,結果良率太低全部焊完之後一塊正常運作的板子都沒有(# 第五代 「算了,還是 back to basic 好了。」用這種邏輯而畫的版子。只提供了最基本的電源、USB port 信號 routing 跟 USB Hub 的晶片,結果雖然有一點問題,但是加一點 patch wire 之後總比一大堆線要好。可是這體積,應該還能再小一點? 第六代 因為考慮到能不能把良率超低的 FE1.1S 找 OEM 進行焊接,然後以模組的形式插回到主板上而開發的板子。基本上與第五代的設計一樣,就是把 FE1.1S 的 footprint 換成了 2.54 針腳的插槽 可是後來這版本並沒有進行生產,因為問了才知道這麼少的生產量走一趟 OEM 貼片實在太貴了(比起買 USB hub 模組回來拆還要貴),所以就這樣這東西就放置了 1年多(由 fyp 開始到 grad 我都沒碰過這計劃) 第七代 在香港疫情爆得最厲害的時候因為在家裡沒事幹所以抽了點時間來設計這塊板子。這基本上是基於第七代的設計,但是把多餘的板子部分切走,讓它最小化方便安裝。可是沒進行生產的原因也是跟第七代一樣。另外你也能看到背面原本要放移充主板的位置被一塊 Powermanv5 代替。 主板背面,使用自家開發的 Powermanv5r2 主板代替移充主板,這樣就不用每做一台 ArOZ Portable 就犧牲一塊移充 背面用來供電跟充電的 Powermanv5r2,也是自家開發的其中一種通用模組,已經量產 https://www.tindie.com/products/tobychui/powerman-power-boost-lipo-charger-inoutput-5v-2a/ 第八代 經過這一年來不斷來回生產不同的 PCB 來做 STEM Kit 跟 了解了更多不同類型的晶片供應商,現在終於有技術可以重新回到這個 project 了。在幾個巧合的情況下才讓我有辦法設計到這塊板子: 在 twitter 看到有工程師分享一塊 SOP16 的 USB Hub 晶片:SL2.1A在拆移充時發現了一塊更便宜的充放管理晶片:HT4928我已經開發好 Powerman 跟 Powerloli 兩塊通用鋰電池充放管理板(內置升壓功能)終於理解 When in doubt, ground it out (有懷疑不知道它要連哪裡的時候,就把它接地吧)的道理 後面可以直接拉線到 Raspberry Pi Zero W 的 test pad 供電和 USB 接口 然後就是等 Power Loli v2 的樣品 PCB 回來,測試過沒問題之後就可以正式生產這塊第 八代的板子了。 8 May…
用了三年時間寫網頁桌面作業系統的故事
這是一個想找地方儲存他的音樂、影片跟圖片的窮學生與他的 Raspberry Pi 的故事。 如果你想直接下載來玩,這裡是傳送門:https://github.com/tobychui/arozos 開始時候的樣子 由 2016 年開始,我就一直在寫這套自用的系統。這系統主要是用來存放音樂、影片檔案等等的媒體文件,這樣我就可以很方便的在課堂跟課堂之間的休息時間聽到自己的音樂或是看一套短劇。這是這套系統於 2016 年的時候的樣子 這個版本是使用 PHP5 開發,後來升級到了 PHP 7 + Apache 伺服器。雖然同一台主機(當時我還是在用我的主機來當伺服器)上面有安裝到資料庫,但是它本身是不需要連接到 MySQL 資料庫的。這系統基本上是使用膠水語言黏起來的,運作原理就是後台的一個 VB.net 程式定時把硬碟上的音樂檔案掃描,並產生一個音樂列表讓 php 去 render 一個網頁界面。當有需要的時候再從硬碟裡搬出來到網頁伺服器的資料夾再進行串流。 你現在依然能夠在我的 Github 找到最原始版本的 ArOZ Online 系統(後來才改名為 ArozOS 作業系統),但是拜托 不!要!用!它!https://github.com/tobychui/ArOZ-Omega-Online 由 PHP 到 Go:開發難度與效能的平衡 這個非常簡單的 PHP 版本使用一兩年之後,因為我開始在上面放越來越多的檔案,單一頁面已經無法應付所有檔案的列表,所以開始加入檔案管理器、模組化的播放器到最後的網頁桌面 不過兩年後,PHP 的系統還是無法應付很多大型檔案(特別是現在的檔案都越長越大,由以前幾 MB 的 mp3 到現在隨時到 50 - 60MB 的 flac 檔案),加上桌面系統做得越來越像本地端的桌面,而需要大量而且高反應速度的資料回傳,因此 PHP 已經沒辦法再成為這系統的主力語言,而需要轉移到另一種語言繼續開發。有興趣了解更多關於這部分的技術問題可以看這篇: http://imuslab.com/wordpress/2020/03/29/%E7%B7%A8%E7%A8%8B%E8%AA%9E%E8%A8%80%E7%9A%84%E6%A5%B5%E9%99%90%EF%BC%9Aphp/ 最後經過一點研究之後,我決定轉移到 Go 語言,並把 ArOZ Online Beta (AOB)正名為 ArozOS 。 3 年後的 ArozOS 系統 經過 3 年的開發,它終於成為了一個類本地作業系統的網頁系統。首先就讓我們由桌面開始介紹吧! 網頁桌面 ArozOS 的桌面基本上就是 Ubuntu 20.04 混 Windows 的風格。你可以看到類似 Ubuntu GNOME 的通知欄 也能夠在右上角看到電源開關(可以透過啟動參數關閉這功能),還有一些方便的捷徑 就像 Windows 一樣,如果你要建立一個新檔案也只需要右鍵即可。你也可以透過右鍵選單來更改桌面背景 開始功能表也是如此,看著有沒有一點熟悉的感覺? 在結束桌面的介紹之前最後一定要說的:桌面版的重新命名界面! 看到沒有彈出視窗的感覺是不是非常有桌面的感覺呢?是不是有那種回到家對著主機螢幕的那種安心感(不對 檔案管理員 在使用原本的系統一段時間之後,我開始需要上載其他東西到我的系統裡。而最通用的界面去查看不同類型的檔案當然是?沒錯,就是檔案管理員。所以我就自己寫了一個進去我的系統啦 我的檔案管理員有兩種模式,為別是「列表」模式跟「縮圖」模式 在縮圖模式下,檔案管理只會嘗試從檔案中提取預覽圖片。這功能適用於音樂、影片,照片甚至 3D 模型檔案 檔案管理員最初並沒有分類和排序的功能。可是由於上載到系統的檔案數目日益增加,所以去到一個地步我還是需要把排序功能加進去才有辦法找到我的檔案( 之後還加入了支援 regex 的檔案尋找功能 噢,如果你是喜歡 dark theme 的使用者,檔案管理員也提供 dark theme 模式,不過這最初只是方便我在晚上找電影來看而已 檔案管理功能 檔案管理員提供很多不同的檔案功能。你可以在右鍵選單中找到所有的功能。 就如作業系統一樣,你也可以選擇以某一個 WebApp 開啟指定的檔案 為了讓自己在收拾和清理資料夾的時候比較方便,所以系統也加入了支援 drag & drop (拖放)的功能。要移動檔案的時候只要很簡單的把檔案由一個視窗拖放到另一個視窗即可。 由於 Golang 本身提供 async 模式以處理要求(request),因此這樣的功能比起 PHP 更容易開發。這個即時的進度顯示是使用 websocket 技術,讓後端一邊複制檔案一邊回傳進度。 檔案分享 間中我也會有需要透過 ArozOS 分享檔案的功能。因此我就順便把這個功能加進去了。 (這裡只是一個例子,乖孩子不要把 localhost 的網址分享給別人喔) 別人就可以透過 QR Code 或是分享的連接來下載到檔案 回到原點:音樂與影片播放 當然這些功能現在還存在吧!經過三年的開發,這些功能已經比之前的好用很多了。使用 PWA 技術,現在的音樂播放器大約長這樣 這個界面甚至可以在 Android 手機上顯示獨立的播放界面(如果你是工程師,這個叫 MediaSession API) 影片播放模組亦是如此。使用 HTML5 技術,它能夠串流影片和電影,不再需要好像以前的版本那樣先下載才能看了。 系統設定 基本設定 由於這套系統已經長這麼大,這麼複雜了,要管理這套系統亦會需要一個很複雜的設定界面。我嘗試把設定界面做得簡單易用,所以就設計了一個分類,讓不同的設定放在不同的子分類裡,然後下面再有不同功能設定的細分類。 首先,你可以在系統設定看到系統的基本資料與處理器、記憶體使用量。 WebApp (網頁應用程式)及 Subservice (子服務) 當然,作為一個網頁桌面系統,當然也需要一個安裝應用的界面吧?所以我就弄了一套應用系統出來了。以下是一堆我寫出來自用的應用程式 WebApp 都是一些簡單,只需要檔案存取的應用程式。這些 WebApp 使用 JavaScript 編寫,並使用 Otto VM 作沙盒隔離。而 Subservice 則是一些比較複雜,需要直接與 OS 連接的程式。 你可以輕易的透過設定界面安裝和移除 WebApp 可是 Subservice 只能設定啟用和禁用。畢竟有一些 subservice 是跟系統運作穩定性相關的,理論上應該是由裝置的…
從零開始的 IoT 系統設計
說到 IoT (物聯網)很多人第一時間就會想起 Google Home ,Apple HomeKit,Amazon Echo 之類的智能喇叭(音箱),但是他們並不是真的跟 IoT 有關,他們比較像是一個輸入裝置或是一個 gateway 去控制其他裝置而已。 另外比較有技術背景的人可能會想起一些 IoT 的技術,好像說 Bluetooth BLE,Zigbee,2.4Ghz RF 跟 IR 之類的傳輸技術,也有另外一些人會想起 IFTTT、MQTT 之類的通訊協議。可是我們這次不是要說這個,而是 怎樣從零開始自己幹一套 IoT 控制系統出來 嘛,雖然說是從零開始但是總不能從沙開始煉硅晶吧?所以這裡的零界定為: 不使用任何專門為 IoT 設計的產品或軟件來制作這套 IoT 系統。 托比 因為之前我在高中畢業到大一之間的暑假我也曾經研究過一套叫 Home Dynamic 的 IoT 系統,所以這套東西就沿用這個名字叫做 Home Dynamic v2 吧! 選擇硬體平台 如果要開發物聯網系統,最基本的話就是需要有「物聯網」中「物」的部分吧?所以我就先由硬體開始選擇。這裡我有幾個要求 便宜,而且容易買到體積要夠小,而且輕便省電(因為要 24/7 的運作) 所以這裡就直接省卻了基於 ARM 處理器的開發板了。剩下的就只有 Arduino 系列用的 ATmega 或是更省電的 ATtiny 或者 ESP 系列的 ESP8266 或 ESP32 選擇連接協議 到了「物聯網」中「聯」的部分,到底要怎樣讓這塊板子連接到其他裝置上?市面上有很多不同的 IoT 連接協議及相關的硬體,常見的包括: Zigbee (通常用在 Mesh 網絡上 )Bluetooth BLE (通常用在需要超省電的裝置上)LoRa (通常用作長距離通訊)2.4Ghz RF (通常用作即時控制,如搖控車)WiFi (對,就是你手機筆電在用的那個 WiFi) 這裡的選擇其他也滿簡單的。首先,LoRa 一定用不上,香港的房子連轉身的空間也沒有,能連接數公里距離的 LoRa 一點用途都沒有。 Zigbee 的確是其中一個可以考慮的選擇,但是因為我也想透過現有的 ArozOS 系統控制它,而 Android、Windows 等作業系統都沒有原生支援 Zigbee,所以在這裡也不作考慮。 最後只剩下 3個選擇:BLE,2.4Ghz RF 跟 WiFi ,不過反正大家都是 2.4Ghz,而且因為我的 IoT 裝置都是用來控制電源、或是用來檢測太陽能板等很容易都抓到電源的地方,那當然選擇最容易可以透過不同手提裝置控制的選擇:WiFi 選擇網絡連接方式 說到「物聯網」的「網(絡)」,既然都跑 WiFi 了當然是用 HTTP 啊!雖然也有其他連接方式例如 MQTT 之類的,但是在選擇這個技術之前要考慮到幾點 這種技術會不會有 SPOF (Single Point of Failure)這種技術會不會需要額外的伺服器 / 硬體這種技術開發起來方不方便(畢竟是寫給自己用,賺不了錢所以太複雜了反而沒意思) 所以就用最簡單的 GET request 就好了啦。而且這方法也不需要 ESP32 內置的藍牙硬體,所以我們可以直接選擇最便宜的 ESP01 來做我們的控制器,一石二鳥。 可是,我們怎樣從網絡中找到 IoT 裝置? 這是一個好問題,而且之前我在開發 Home Dynamic 系統的時候也遇過類似的問題。但是作為剛剛升大學的我,當時我使用了一個最原始的方法:每個 IP ping 一次 但是在這次的開發計劃中(我把它叫做 Home Dynamic v2),我打算使用 mDNS 來取代這個(爛)IP 掃描方法。畢竟比起一次過把整個區網 ping 一次,例不如讓裝置自己 broadcast 自己的信息好了。剛好 ArozOS 也有內置到 mDNS 掃描器,所以就直接拿來做 IoT 掃描器不就行了嗎? 於是,我把 mDNS 的 transponder 塞到 ESP8266 裡面,然後跟據 ArozOS 的 mDNS transponder 結構寫了個這樣的 metadata 到 transponder 的回應信息裡面。以下為 hdsv2 的電源開關控制器的代碼: //Inject zeroconf attr into the MDNS respond (For scanning by ArozOS) void…
在 Go 伺服器上加入 Gzip Middleware 中繼器
話說最近因為有使用者提出想把 ArozOS 放到 Cloud VM 上面跑,所以想盡量壓縮 bandwidth 使用量,經過一大堆討論之後的結論就是在伺服器主要的檔案傳送之前先加個 gzip 壓縮器。 現時網上對於要應用 gzip middleware (我把它譯做「中繼器」,畢竟叫他做「中介軟體」好像怪怪的,跟中國大陸的叫法叫「中間件」又好像不太能表達意思) gzip middleware 原理 這個原理很簡單,就是在資料發出去之前先經過一層 gzip 以減少傳送的資料量,系統由原本的 要求 --> Mux / Router --> Handler --> 回傳 變成 要求 --> Mux / Router --> Handler --> gzip 壓縮 --> 回傳 因為要解釋起來很麻煩所以我就直接把 Go module 放這裡了: https://gist.github.com/tobychui/e31ca5be46e266cf52fc247dd38c9181 以下是一些使用例子: if *enable_gzip { http.HandleFunc("/media/", gzipmiddleware.CompressFunc(serverMedia)) }else{ http.HandleFunc("/media/", serverMedia) } fs := http.FileServer(http.Dir("./web")) if *enable_gzip { //Gzip enabled. Always serve with gzip if header exists http.Handle("/", gzipmiddleware.Compress(fs)) } else { //Normal file server without gzip http.Handle("/", mroutner(fs)) } 效果 以 ArozOS 的 desktop.system 界面來看,節省的流量大約如圖所示 上:有開啟 gzip 中繼器 下:沒有開啟 gzip 中繼器 嘛,基本上就這麼簡單而已。
目前第 1 頁,共有 3 頁