2025年2月19日 星期三

Ubuntu Apache SSL設定紀錄問題檢查常用指令

環境面:

- DNS需要設定IPV4, IPV6指向

- LightSail只有預設IPV6的443防火牆規則,需要另外新增IPV4的規則


Apache設定

- path: etc/apache2/

- port.cong: 

    要確認有Listen 443, Listen  [::]:443

- /sites-available/default-ssl.conf (預設設定檔)

    修改ServerAdmin、ServerName、DocumentRoot

    SSLEngine on

    憑證檔:

    SSLCertificateFile:預設路徑/etc/ssl/certs/

    SSLCertificateKeyFile:預設路徑/etc/ssl/private

    SSLCertificateChainFile:預設路徑/etc/ssl/certs/

    *apache 80預設值在000-default.conf中,不需異動

- 確認憑證讀取權限

    - 將檔案上傳預設路徑時會需要異動讀取權限,上傳後再改回來

    - sudo chmod 644 憑證.crt

    - sudo chmod 600 key.pem

    - sudo chmod 755 目錄

    - sudo chown www-data:www-data 憑證.pem

    - sudo chown www-data:www-data key.pem


異常檢查指令:

-查看Apache運行錯誤

 sudo tail -n 50 /var/log/apache2/error.log


-查看Apache設定錯誤

 sudo apachectl configtest



-強制關閉、清除、啟動、重啟

 sudo systemctl stop apache2 

 sudo killall apache2

 sudo systemctl start apache2

 sudo systemctl restart apache2


-檢查是否有其他應用程式在使用443,80port

 sudo netstat -tulnp | grep -E "80|443"


- 檢查443是否正確讀取:

  sudo netstat -tulnp | grep ":443"

  顯示為tcp6       0      0 :::443                  :::*                    LISTEN      485/apache2 
  

-測試SSL憑證鍊
 openssl s_client -connect d0works.com:443 -showcerts

-測試https網址

2024年6月29日 星期六

REMOTE HOST IDENTIFICATION HAS CHANGED- 遠端連線同IP但主機變更出現的問題

當遠端連線的IP之前曾經連過,但該IP的主機變了,就會出下以下錯誤:


 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!

Someone could be eavesdropping on you right now (man-in-the-middle attack)!

It is also possible that a host key has just been changed.

The fingerprint for the ED25519 key sent by the remote host is

SHA256:Z6o3XAafMD3s3RGM/s2sX1XYz8QXBwY2Aw+UhHc5cT4.

Please contact your system administrator.

Add correct host key in C:\\Users\\rex_h/.ssh/known_hosts to get rid of this message.

Offending ECDSA key in C:\\Users\\rex_h/.ssh/known_hosts:27

Host key for 192.168.1.113 has changed and you have requested strict checking.

Host key verification failed.


重新移除先前儲存的ssh Key

ssh-keygen -R [ip]

2024年6月26日 星期三

數莓派 bookworm 設定固定IP

數莓派Bookworm因為沒有預設dhcpcd,所以無法使用之前dhcpcd.conf來進行固定IP設定。

如自行安裝dhcpcd/dhcpcd5會出現預設桌面變成debian,還有關機前會需要等1分半來進行網路服務關閉的狀況。


查到國外針對bookworm的設定資訊做個紀錄: 資料來源


查詢連線裝置資訊

sudo nmcli -p connection show


如下回應: 

NAME        UUID                                  TYPE      DEVICE

----------------------------------------------------------------------------------------------------------

有線連線 1  899107fa-3f50-38b7-8f44-2893f2fa0b68  ethernet  eth0


設定IP: 

sudo nmcli c mod "有線連線1" ipv4.addresses 192.168.1.220/24 ipv4.method manual


設定Gateway: 

sudo nmcli con mod "有線連線1" ipv4.gateway 192.168.1.1


設定DNS: 

sudo nmcli con mod "有線連線1" ipv4.dns 192.168.1.1


重啟網路連線

sudo nmcli c down "Wired connection 1" && sudo nmcli c up "Wired connection 1"

2024年6月6日 星期四

數莓派 關閉run.log

基本邏輯是將log引導到null 就不會去寫資料了


進入桌面設定檔

 sudo nano /etc/xdg/lxsession/LXDE-pi/desktop.conf


在session區塊加入
[Session] 
log_file=/dev/null


要關閉的程式設定在autostart file中
進入設定檔
nano ~/.config/lxsession/LXDE-pi/autostart

在執行命令後加上> /dev/null 2>&1

建立null 連結
刪除run.log 再建立null連結
rm /home/pi/.cache/lxsession/LXDE-pi/run.log 
ln -s /dev/null /home/pi/.cache/lxsession/LXDE-pi/run.log

重新開機

2023年9月22日 星期五

數莓派 開關機按鈕

參考資料來源

根據大大的分享,開關機按鈕比預期的簡單。

只要在/boot/config.txt 最後加上以下段落

dtoverlay=gpio-shutdown



然後將 2pin按鈕的兩根線接上下圖GPIO3, Ground兩個Pin腳就完成了。



另外,建議用2pin無段按鈕

這開關行為是 關機(off)時按下開機(on);開機(On)時,按下 關機(off),


如果是買1/0的翹翹板開關可能會發生,1變成關,0變成開;或者要關開一次開機,在開關一次關機


--- eeprom conifg 設定

用來設定GPIO啟動參數

編輯指令:

sudo -E rpi-eeprom-config --edit


WAKE_ON_GPIO=1 (設定可以用GPIO來啟動數莓派)

POWER_OFF_ON_HALT=1 (當WAKE_ON_GPIO=0, 且此項=1時,在HALT後GPIO則不供電)


2023年6月17日 星期六

[數媒派]修改pi帳號

預設root 帳號關閉,且ssh 不允許root連線;系統只有預設PI,但有消息指出之後不會再有預設PI帳號,待確認後續OS版本。

先使用pi帳號登入,再執行以下動作:

1) 啟用root帳號

- sudo passwd root

- 輸入root帳號密碼

2) 解鎖root帳號

- sudo passwd -u root

- 解鎖後可以透過遠端連線來使用root帳號登入,但還無法使用ssh登入

3) 設定ssh連線

- sudo nano /etc/ssh/sshd_config

- 找到PermitRootLogin的位置,新增一行PermitRootLogin yes

- 儲存檔案後,重新啟動;便可使用root帳號登入

4) 以PI帳號登入,在raspberry 設定中 關閉自動以pi登入功能


變更pi帳號

再變更pi帳號前要使用root帳號登入,以root登入後執行以下動作:

-sudo usermod -l newpi pi

- 以上指令將pi改為newpi

-usermod -m -d /home/newpi newpi

以上指令修改目錄pi為newpi

- 修改後newpi這個帳號仍擁有pi帳號的權限


關閉root帳號

- sudo passwd -l root

- sudo nano /etc/ssh/sshd_config

- 找到PermitRootLogin的位置,註解掉本來增加的PermitRootLogin yes


設定autostart

- cd  .config/lxsession/LXDE-pi/

- 在此路徑中新增autostart

- autostart指令

    @command

這樣重開機後,就會用newpi 登入並自動執行程式


參考資料

參考資料

參考資料

2022年12月8日 星期四

購車心得 CC Corolla Cross 油電豪華 + 影音套件 (讓我意外的事)

新手購車,單純分享購車後讓我有點意外的地方,還有覺得購車前準備不足的地方。


時速30以上才會反應的A柱盲點偵測(BSM)

交車後開在路上就發現,怎麼旁邊機車經過盲點沒有動作?

再回廠找業務上車測試,業務也答不上來;經測試幾次整理如下:

  - 30以上才會有反應

  - 當打方向燈,偵測到有車時會快速閃爍

PS. 原廠的後視鏡BSM(尊爵、旗艦版)啟動時速應該小於30KM。停等紅綠燈時有看到CC、 RAV4幾乎到停住才消失的後視鏡BSM燈號,建議在乎BSM功能的人,千萬要買尊爵以上版本

以個人行車經驗來說,市區的低速轉彎因為機車、腳踏車,或行人在視線死角造成意外,盲點警示功能也很重要。


只亮1/3 的LED尾燈

由於現場沒車,問業務時他也只說豪華版的尾燈跟其他款一樣,只是裡面是LED燈泡,不是光條。

- 結果後來才發現只有車身左右那兩點會亮,尾門的部分不會亮。




前霧燈跟後霧燈分兩個開關,後霧燈原來只有一小格

只有旗艦版有前霧燈,其他版本只有後霧燈;所以決定加裝前霧燈。

- 但後霧燈開關在燈光控制把手上,前霧燈開關在左側冷氣口的下方面板

- 而且後霧燈是在左後尾燈組尾門上的一小格... 




購車過程回顧起來讓我覺得做錯的地方,分享給各位:

1) 沒先對報價結構做功課: 

- 購車總費用= (原車價- 空車業務折扣) + (配件價格- 業務配件折扣) + (保險 - 業務折扣) + 領牌手續費 , 有貸款的話再加上貸款息

- 一開始業務可能會說,可以折5萬、7萬... 其實都是有條件的;應該要先確認需要的項目再進行詢價跟比價

- 尤其像保險我覺得價差也蠻大的,連車買的乙式車險要四萬多再退傭幾千到1.5萬;但我自己保其他產險公司只要兩萬。


2) 應該先在網路詢價:

大多數的業務都可以跨區做生意,而且看來有些業務願意給的折扣比較多,再到門市之前應該先在網路上徵菜單詢價。

- 每區的業務報價的貸款息跟保險退傭可能有些差異,應該多問才比較能找到理想的金額


3) 優惠只到今天的話術:

今天做決定可以再折多少....

- 當有做前兩項後,再降台時聽到業務這樣說,就可以帥氣的走人了;不折其實找其他家的業務就好


4) 這個月領牌的車可以多折多少或下個月會貴多少,但這個月只有XX車... 

- 本來只想買油電尊爵,但就因為當月沒有生產尊爵版的車所以改成豪華再加影音套件

- 業務為了拚當月業績會說這種話,所以我在11月中下訂了;結果12月交車時再用幫其他人問的名義問一次價格...  還不是一樣!  那為什麼不直接等下個月初在訂想要的車款。


總之,開新車還是很開心。 

但如果功課有做足,購車過程跟拿到車使用後應該會更開心。


2022年11月14日 星期一

[Python] 透過python編輯文字檔

 import os


#清除檔案中的文字後關閉

f= open('/home/pi/Documents/test.txt', 'w').close()


#在現有檔案中寫入新文字

f=open('/home/pi/Documents/tmrtV05/test.txt','a')

testStr=('This texts for test \n'+

    'and TEST')

f.writelines(testStr)

f.close()


會寫入以下文字到/test.txt中

This texts for test 

and TEST


2022年10月14日 星期五

[Python]中文編碼轉換Unicode

透過python搜尋SSID時, 發現會變成Unicode,所以查了一下編碼跟解碼的方法。

SSID看來編碼方式是utf-8,但其實編碼方式蠻多的,就列出來可以看一下長相。

以下程式碼:

#coding:utf-8

import sys


chStr='中文字En'

print (chStr,type(chStr))

輸出: 

中文字En <class 'str'>

print ('-轉utf8------')

UTF8_chStr=chStr.encode('utf-8')

print (UTF8_chStr,type(UTF8_chStr))

UTF8_chStr_decode=chStr.encode('utf-8').decode('utf-8')

print (UTF8_chStr_decode,type(UTF8_chStr_decode))

輸出: 

-轉utf8------

b'\xe4\xb8\xad\xe6\x96\x87\xe5\xad\x97En' <class 'bytes'>

中文字En <class 'str'>


print ('-轉utf16------')

UTF16_chStr=chStr.encode('utf-16')

print (UTF16_chStr,type(UTF16_chStr))

UTF16_chStr_decode=chStr.encode('utf-16').decode('utf-16')

print (UTF16_chStr_decode,type(UTF16_chStr_decode))

輸出: 

-轉utf16------

b'\xff\xfe-N\x87eW[E\x00n\x00' <class 'bytes'>

中文字En <class 'str'>


print ('-轉gbk------')

gbk_chStr=chStr.encode('gbk')

print (gbk_chStr,type(gbk_chStr))

gbk_chStr_decode=chStr.encode('gbk').decode('gbk')

print (gbk_chStr_decode,type(UTF8_chStr_decode))

輸出: 

-轉gbk------

b'\xd6\xd0\xce\xc4\xd7\xd6En' <class 'bytes'>

中文字En <class 'str'>


print ('-unicode_escape------')

uni_chStr=chStr.encode('unicode_escape')

print (uni_chStr,type(uni_chStr))

uni_chStr_decode=chStr.encode('unicode_escape').decode('unicode_escape')

print (uni_chStr_decode,type(uni_chStr_decode))

輸出: 

-unicode_escape------

b'\\u4e2d\\u6587\\u5b57En' <class 'bytes'>

中文字En <class 'str'>


2022年9月26日 星期一

[Python]透過Python 程式連線無線網路- pywifi 使用

[pywifi參考網址]


概念是將無線網路參數加入wpa_supplicant.conf來進行連線,若不用語法控制,其實直接將網路資訊設定在wpa_supplicant.conf中也可以。

位置:

sudo nano/etc/wpa_supplicant/wpa_supplicant.conf


設定值:
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
country=TW

#無加密網路
network={
        ssid="test"
        key_mgmt=NONE
        disabled=1
}

#有加密網路
network={
        ssid="test2"
        psk="password"
        key_mgmt=WPA-PSK
}


安裝Pywifi

pip install pywifi


連線範例程式:

import pywifi

import sys

import time

from pywifi import const


wifi=pywifi.PyWiFi()

ifaces= wifi.interfaces()[0]

profiles = ifaces.network_profiles()


ifaces.disconnect()

profile=pywifi.Profile()

profile.ssid="[無線網路名稱]"

profile.key="[無線網路密碼]"

profile.auth=const.AUTH_ALG_OPEN

profile.akm.append(const.AKM_TYPE_WPA2PSK)

profile.cipher=const.CIPHER_TYPE_CCMP

#移除舊的設定參數

ifaces.remove_all_network_profiles()

#加入新的的設定參數

new_profile=ifaces.add_network_profile(profile)

time.sleep(2)

print('add profiles.ssid:'+str(profiles[0].ssid))

print('------')

#進行連線

ifaces.connect(new_profile)

#等候連線

time.sleep(10)


測試經驗是 pywifi的狀態檢查通能不太可靠,等候連線的時間可能10秒到1分鐘以上。


相關profile參數補充如下:

# Define interface status.

IFACE_DISCONNECTED = 0

IFACE_SCANNING = 1

IFACE_INACTIVE = 2

IFACE_CONNECTING = 3

IFACE_CONNECTED = 4


# Define auth algorithms.

AUTH_ALG_OPEN = 0

AUTH_ALG_SHARED = 1


# Define auth key mgmt types.

AKM_TYPE_NONE = 0

AKM_TYPE_WPA = 1

AKM_TYPE_WPAPSK = 2

AKM_TYPE_WPA2 = 3

AKM_TYPE_WPA2PSK = 4

AKM_TYPE_UNKNOWN = 5


# Define ciphers.

CIPHER_TYPE_NONE = 0

CIPHER_TYPE_WEP = 1

CIPHER_TYPE_TKIP = 2

CIPHER_TYPE_CCMP = 3

CIPHER_TYPE_UNKNOWN = 4


KEY_TYPE_NETWORKKEY = 0

KEY_TYPE_PASSPHRASE = 1


搜尋無線網路範例程式:

wifi=pywifi.PyWiFi()#建立一個wifi物件

ifaces= wifi.interfaces()[0]#取第一個無限網絡卡

print(ifaces.name())#輸出無線網絡卡名稱

ifaces.scan()

scanResult = ifaces.scan_results()

time.sleep(10)

if scanResult is not None:

    for profile in scanResult:

        ssid = profile.ssid

        print(profile)

        print('SSID:'+profile.ssid)

        print('AUTH:'+str(profile.auth))

        print('cipher:'+str(profile.cipher))

        print('AKM:'+str(profile.akm))

else:

    print ('未找到wifi')

2022年7月5日 星期二

[JS]等候一段時間後執行 setInterval

設定延後一段時間在執行某個動作

setInterval( function(){[某個動作]},[延後毫秒]);


Sample:

setInterval(function(){

    console.log('等一下~')}, 2000); 


[JS]字串轉為數值, String to Number

因為JS會自動判斷資料型別進行運作處理,有時判斷錯誤就會出現無法理解的結果;如下例子:

透過API取得

data{

    TimeA:'3',

    TimeB:'4',

    TimeC:'5'

}

透過以下算式計算totalTime

totalTime =(data.TimeA+data.TimeB+data.TimeC)*10

console.log('totalTime:'+ totalTime)

=>3450

因為變成字串('3'+'4'+'5')*10=>3450


須將字串改為數值,如下:

totalTime =(Number(data.TimeA)+Number(data.TimeB)+Number(data.TimeC))*10

console.log('totalTime:'+ totalTime)

=>120



2022年6月30日 星期四

[JS]取得網址及相關參數

網址範例: http://hugtest.com/test.html?id=2


取得完整網址

href=location.href

console.log('location.href:'+href) -> http://hugtest.com/test.html?id=2


取得Host

host=location.host

console.log('location.host:'+host) -> hugtest.com


取得Protocol

protocol=location.protocol

console.log('location.protocol:'+protocol) -> http:


取得網頁路徑

pathname=location.pathname

console.log('location.pathname:'+pathname)->test.html


取得search 文字

search=location.search

console.log('location.search:'+search)->?id=2


取得參數內容

urlPara=new URL(href) //href為上方的完整網址

para=urlPara.searchParams.get('id') //id為上放要取得的參數名稱

console.log('para:'+para)->2


檢查是否有參數

urlPara=new URL(href) //href為上方的完整網址

ispara=urlPara.searchParams.has('id') //id為上放要取得的參數名稱

console.log('ispara:'+ispara)->true


2022年6月25日 星期六

[JS]日期Date函式

透過JS Date可取得時間參數

date=new Date()

date.xxxxx() 各Function結果如下:

.toLocaleString() -> 2022/6/26 上午9:30:16

- 本地時間字串


.toUTCString() -> Sun, 26 Jun 2022 01:30:16 GMT

- 格林威治時間,星期,dd mm yyyy hh:mm:ss


.toISOString() ->2022-06-26T01:30:16.107Z

.toJSON()-> 2022-06-26T01:30:16.107Z

- toISOString(), toJSON() 回傳值相同


.toLocaleTimeString()->上午9:30:16

- client本地時間


.toTimeString ->09:30:16 GMT+0800 (台北標準時間)

- client本地時間

- 若要取時間格式hh:mm:ss 則可用date.toTimeString().subString(0,8)取得時間部分


.toDateString()->Sun Jun 26 2022

- client本地時間


.toLocaleDateString()->2022/6/26

- client本地日期


.getFullYear()->2022

- client本地時間,此方法可完整顯示yyyy


.getYear()->122

- 此方法顯示122;由1900年後開始計算,因此2022-1900=122


.getMonth()->5

- client本地月,從0開始計算,因此要+1


.getDate()->26

- client本地日


.getDay()->0

- client星期


.getTimezoneOffset()-> -480

- client與格林威治時區的時差(分)


----

date=new Date()
console.log('getTime():'+date.getTime())
console.log('getUTCHours():'+date.getUTCHours())
console.log('getUTCMinutes():'+date.getUTCMinutes())
console.log('getUTCSeconds():'+date.getUTCSeconds())
console.log('getUTCDate():'+date.getUTCDate())
console.log('getUTCDay():'+date.getUTCDay())
console.log('getFullYear:'+date.getFullYear())
console.log('getYear:'+date.getYear())
console.log('getMonth:'+date.getMonth())
console.log('getDate:'+date.getDate())
console.log('getTimezoneOffset:'+date.getTimezoneOffset())
console.log('toDateString:'+date.toDateString())
console.log('toISOString:'+date.toISOString())
console.log('toLocaleDateString:'+date.toLocaleDateString())
console.log('toLocaleString:'+date.toLocaleString())
console.log('toUTCString:'+date.toUTCString())
console.log('toJSON:'+date.toJSON())
console.log('toLocaleTimeString:'+date.toLocaleTimeString())
console.log('toTimeString:'+date.toTimeString())




2022年5月28日 星期六

Tinker Board S2 遠端設定 tightvncserver, 遠端桌面

使用VNC Viewer登入

若是新系統要進行設定,則先更新:

sudo apt upgrade

sudo apt update

1) sudo apt-get install xfonts-base (沒有安裝這個會無法成功安裝tightvncserver)

2) sudo apt-get install tightvncserver

3) vncserver

- 開始設定8碼密碼



4) 查看VNC是否執行 sudo ps a | grep vnc

- 有看到如下資訊表示有啟動,5901是連線Port



5) 可以從VNC viewer 輸入 ip:5091 進行連線;

- 再輸入帳號密碼(上面設定的8碼)就可以登入了


-- 使用windows遠端桌面: 

新系統的話要先更新

sudo apt upgrade

sudo apt update

1)  sudo apt-get install xrdp 

2) sudo apt-get purge xrdp

3) sudo /etc/init.d/xrdp restart

4) 查看Port狀況 netstat  -tnl 

    確認LISTEN 5910,3350,3389 


4) sudo apt-get install tigervnc*

5) 開啟windows遠端桌面,輸入IP位置;

在以下畫面要選擇xvnc,再輸入帳號密碼就可以登入了。






2022年5月27日 星期五

[Mac] REMOTE HOST IDENTIFICATION HAS CHANGED!

當同個IP的主機變更後,會導致原本存在本機的識別碼與新主機不符;

可透過以下方式處理:

[Mac]: 

方法一) ssh-keygen -R [IP位置]

方法二) 移除存在 .ssh/known_hosts 的該IP 位置參數,如下圖:

    刪除後即可再重新連線


2022年5月22日 星期日

Tinker Board 2S GPIO Input/Output Sample

Tinker Board 2S 的Image檔已經有GPIO SDK不用另外下載。

Python 安裝方法如下:

cd /usr/local/share/gpio_lib_python_rk3399

sudo python setup.py install

sudo python3 setup.py install


以下目錄有範例程式:

cd /usr/local/share/gpio_lib_python_rk3399/test/ 

(PS. 一開始我下載到Tinker Board的Library,就會出現錯誤訊息)


Tinker Board GPIO  PIN說明:



目前測試起來跟樹莓派的語法相同:

測試一個3PIN搖頭開關輸入

import ASUS.GPIO as GPIO
import time

#關閉警示
GPIO.setwarnings(False)
#設定Pin No為BOARD
GPIO.setmode(GPIO.BOARD)
#宣告Input Pin
inPort=3
GPIO.setup(inPort,GPIO.IN)
GPIO.add_event_detect(inPort, GPIO.BOTH)
#宣告一個 GND Pin
lowGnd=5
GPIO.setup(lowGnd,GPIO.OUT)
GPIO.output(lowGnd,GPIO.LOW)

#偵測Input迴圈
while True:
if GPIO.event_detected(inPort):
inputVal=GPIO.input(inPort)
print('Val:'+str(inputVal))
else:
print ('--')
time.sleep(0.5)




測試LED閃爍

import ASUS.GPIO as GPIO
import time

#關閉警示
GPIO.setwarnings(False)
#設定Pin No為BOARD
GPIO.setmode(GPIO.BOARD)
#宣告LED PIN
lightP=32
GPIO.setup(lightP,GPIO.OUT)

#開關LED迴圈
while True:
GPIO.output(lightP,GPIO.HIGH)
time.sleep(1)
GPIO.output(lightP,GPIO.LOW)
time.sleep(1)



2022年5月17日 星期二

Tinker Board S2 初始安裝

相較於數莓派 我覺得稍微麻煩一點,爬了些文才完成遠端。

我是買有emmc的版本,設定步驟如下:

1) 用USB type C傳輸線連接tinker board與PC。

2) 板子接上12V的電 (坦白說12V的電讓我顧慮蠻久的,不能用GPIO供電整合其他控制元件上就稍嫌麻煩) 

3) 這時電腦應該會出現找到新的儲存設備(可能還會跳出要求要格式化的提醒)

4) 下載Tinker Board S2 img檔解壓縮(我是下載Debian版本)

5) 下載etcher 載完後安裝;然後選擇img檔,再選擇儲存設備,就可以開始燒錄了。

6) 燒錄完成後,移除USB線。

7) 因為還不能遠端,所以Tiker Board要接上螢幕、鍵盤、滑鼠(我接上螢幕後還沒有畫面,是拔掉電源重新啟動後,螢幕才出現畫面)。


1) 若已接上有線網路,應該可以在preference/ Advance Network Configuration 中看到;

    無線網路設定也可以在這各視窗進行,設定時需要 預設帳號/密碼 (linaro/linaro)

2) 接著啟動LXTerminal查看ip: sudo ifconfig


這樣就完成初步設定,可以進行遠端設定


2022年5月16日 星期一

Flask 網頁 透過下拉選單(select) 顯示不同圖片

還在摸索Flask中,感覺比較大的好處是直接就包含web Server了,

不用另外設定(Ngix, Apache..)。

不太確定有沒有前後端分離的概念,目前測試感覺都是由Flask包好再傳到前端,

速度似乎稍微慢一點。(也有可能是我還不會設定...)


範例程式:

從localhost:8080/ 頁面中的下拉選擇圖片並按下送出後,

進入另一個頁面顯示所選擇的圖片。

由於想要在顯示圖片時,也顯示下拉選單中的圖片名稱,

但不知道Python如何顯示,所以使用Jquery將選單文字加到隱藏欄位,

用Post表單的方式將文字帶出來。



Flask程式目錄下有:

- templete資料夾: 存放html檔案

- static資料夾:存放CSS、圖片、JS檔案...

- 其他就是python檔 


檔案如下:

- python檔sample.py

- 首頁 index.html(存在template中)

- 圖片頁 showImg.html(存在template中)

- CSS檔 sample.css(存在static/css中)

- 圖片檔 sample.css(存在static/images中 請自行找圖喔)

- 另外還有JQuery檔(請自行下載)


python檔: sample.py

PS. 安裝Flask (pip install flask)

from flask import render_template (存取template html資料)

from flask import request (若有透過POST, GET 傳值 則需要request)



import time
import flask
from flask import render_template
from flask import request
import netFunc

#--Flask
app = flask.Flask(__name__)

#首頁路徑Function
@app.route('/')
def index():
    #下拉選單的資料
    imgs=[
        {'val':'cat','text':'貓'},
        {'val':'flower','text':'花'},
        {'val':'rabit','text':'兔子'}
    ]
    #顯示為template中的index.html
    return render_template('index.html',**locals())

#當路徑為submit時,執行的function
@app.route('/p', methods=['POST'])
def showImg():
    #取得圖片選單的value,並加上完整路徑
    imgName=request.values['imgPick']
    imgurl='./images/'+imgName+'.jpg'
    #取得隱藏欄位的value
    imgText=request.values['tmptext']
    return render_template('showImg.html',**locals())


if __name__=='__main__':
    ip='localhost'
    app.run(host=ip,port=8080,debug=True)



首頁 index.html

<!DOCTYPE html>
<html lang='zh-TW'>
<head>
      <meta charset="utf-8" />
      <title>This Sample Page</title>
      <link type="text/css" rel="stylesheet"
          href="{{ url_for('static',filename='css/sample.css')}}" />
      <script src="{{url_for('static',filename='js/jquery-3.5.1.min.js')}}" ></script>
</head>
<body>
      <!--建立POST 方法的表單,並在送出後,將路徑加上submit-->
      <form method="post" action="/p">
            <label>選擇圖片</label>
            <div id="func">
                  <select id="picker" name="imgPick" onchange="getSelect()">
                        {% for i in imgs %}
                        <option value={{i.val}} >{{i.text}}</option>
                        {% endfor %}
                  </select>
                  <!--透過隱藏的欄位記錄選項文字-->
                  <input type="text" name="tmptext" id="tmptext" style="display:none ;"></input>
                  <button type="submit">確認</button>
            </div>
           
      </form>

</body>
</html>

<script>
      //一進入頁面就先取得選單文字並帶入表單tmptext
      $(document).ready(function(){
            selectText=$('#picker').find(':selected').text()
            $('#tmptext').val(selectText)
      })

      //透過JS取得選擇的選項文字
      function getSelect(){
            selectText=$('#picker').find(':selected').text()
            $('#tmptext').val(selectText)
      }
</script>


圖片頁 showImg.html

<!DOCTYPE html>
<html lang='zh-TW'>
<head>
      <meta charset="utf-8" />
      <title>This Sample Page</title>
      <link type="text/css" rel="stylesheet"
          href="{{ url_for('static',filename='css/sample.css')}}" />
      <script src="{{url_for('static',filename='js/jquery-3.5.1.min.js')}}" ></script>
</head>
<body>
    <div id="show">
    <a href="/">回前頁</a>
        <label >所選擇圖片為-{{imgText}}</label>
        <!--圖片會根據Python回傳得imgurl顯示-->
        <img src="{{url_for('static',filename=imgurl)}}" />
    </div>

</body>
</html>


CSS檔 sample.css


form{
    display: block;
    width: 50%;
    height: auto;
    margin: 1px auto;
    padding: 10px;
}

#func{
    margin-top: 10px;
}
label{
    font-size: 18pt;
    color: rgb(3, 84, 84);
    margin: 10px;
}

#picker{
    color: rgb(133, 50, 6);
    font-size: 14pt;
}

button{
    background-color: rgb(3, 84, 84);
    color: white;
}
#show{
    display: block;
    width: 50%;
    height: auto;
    margin: 1px auto;
    padding: 10px;
    margin-top: 10px;
    margin-bottom: 10px;
}
#show a{
    display: block;
    width: 80px;
    line-height: 30px;
    font-size: 14pt;
    text-decoration: none;
    background-color: rgb(200,210,220);
    color: rgb(80,80,80);
    border-radius: 5px;
    text-align: center;
}
#show a:hover{
    background-color: rgb(129, 168, 160);
    color: white;
    border-radius: 5px;
}
#show label{
    margin-top: 10px;
    margin-bottom: 10px;
}
img{
    margin: 10px;
}



2022年5月12日 星期四

JS取得Select選單的值與文字+onchange事件

 下拉選單html sample:

    <select id='fruit' onchange='getInfo(this)'>

            <option value=apple>Apple</option>

            <option value=banana>Banana</option>

            <option value=lemon>Lemon</option>

        </select>


Jquery取得Value:

    $('#fruit').val()

Jquery取得選取的文字:

    $('#fruit').find(':selected').text()


當選單變更選項時觸發事件範例如下:

<html lang="zh-TW">
<head>
<script
src="https://code.jquery.com/jquery-3.6.0.min.js"
integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4="
crossorigin="anonymous"></script>
<!--取得Selecet資料Function-->
<script>
function getInfo(){
fruit=$('#fruit').val()
fruitName=$('#fruit').find(':selected').text()
showInfo='Val:'+fruit+'|Name:'+fruitName
$('#info').text(showInfo)
}
</script>
</head>
<body>
<!--Select Sample-->
<select id='fruit' onchange='getInfo()'>
<option value=''>-Choose One-</option>
<option value=apple>Apple</option>
<option value=banana>Banana</option>
<option value=lemon>Lemon</option>
</select>
<div>
<label>Info:</label>
<label id='info'></label>
</div>
</body>
</html>