2015年10月3日 星期六

NodeMCU 從網上取得時間

基於 : http://softbugbug.blogspot.com/2015/10/python.html

要有全域變數 HH, MM, SS
timer 要數時間
此段程式碼功能為 連上網路更新 HH, MM, SS 的數值

-- ['gettime.lua'] 
-- get time from web
-- update NodeMCU time base on get from web  
url = "http://time.artjoey.com/js/basetime.php"
site = "time.artjoey.com"
loc = "/js/basetime.php"

data = "GET "
  ..loc.." HTTP/1.1\r\nHost: "
  ..site.."\r\nConnection: keep-alive\r\nAccept: */*\r\n\r\n"

sk=net.createConnection(net.TCP, 0)

sk:on("receive", function(sck, c) 
  print("receive") 
  print(c)

  get={string.find(c,"baseTime=")}
  --If GET value exist,
  if get[2] ~= nil then 
    print("P:")
    print(get[2] )   -- print the start location of serch string 
    basetime = string.sub(c, get[2]+1, -7)   -- last char are 000;CrLf.  get basetime
-- example basetime = 1443789637
--  NodeMCU max value 2147483647 
    print(basetime)
    print("before:"..HH..":"..MM..":"..SS)
    esp_update() 
    print("after:"..HH..":"..MM..":"..SS)
  end

end )
sk:on("disconnection", function(sck, c) 
  print("disconnection")
  print(c)
end )
sk:on("connection", function(sck, c) 
  print("connection") 
  print(c)
end )

sk:connect(80,ip)
sk:send(data)

function esp_update() 
  twsec = basetime + 28800  -- 60 * 60 * 8  add 8Hr (tw: GMT + 8)
  daysec = twsec % 86400    -- 60 * 60 * 24
  HH = daysec / 3600        -- 60 * 60
  MM = (daysec / 60) % 60    
  SS = daysec % 60
--  webs()                  -- run http_server after update time
end

題外話:
NodeMCU 的字串連接式為 ..
ex: 
 str1 = "Hellow"
 str2 = str1..123     -- 數值型態的資料在此會自動轉為字串
 print(str2)
 Hellow123

Python 從網路上取得時間

做 client 端的應用時, 想要從網路上取得時間
NTP(網路時間協議) 的取得比較複雜
基於沒有要使用很精準的時間,於是把目標放到找一個有顯示時間的網頁就好了
且網頁內容要簡單,以免 client 端下載時系統資源不敷使用

在google 上找到一個 台灣時間  網頁
用 chrome 的開發人員工具
看到在 id = local_time 的後面有包含時間,這段在紅框標示處
於是把網址(底下橘色畫線)處改為紅框處的內容
http://time.artjoey.com/js/local.htm
到這邊,需要下載的網頁內容已經減少許多
使用 python 抓取網頁
發現在 id = local_time 後面的資料內容是 Clock...
這不是我們要的東西,於是再找網頁內容
在 <head> 中有一段
將紅框中的網址取代上面橙色底線,得到 http://time.artjoey.com/js/basetime.php 

至此,可以看到一個很熟悉的數值 1443....
才怪
此例中的 baseTime 為 從1970/01/01 開始到現在的毫秒數
所以把數值取出來後,先除 1000 換算成秒

以下是一小段 python 程式,演示取出當日時間

# 使用網路資源
import requests
import urllib

url = "http://time.artjoey.com/js/basetime.php"
res = requests.get(url)
# res.content type is <byte>
basetime = res.content.decode('ascii')
# var baseTime=1443757229000;
ms = int(basetime.split('=')[1][:-1])   # 用'='分隔, 取出第二組字串的 開頭到倒數第二字元 (最後字元是分號)
twsec = ms / 1000 + (60 * 60 * 8) # 台灣是 GMT + 8, 要把偏差的秒數加上去
daysec = twsec % (60 * 60 * 24)   # 僅取出當日開始到目前的秒數
HH = int(daysec / 60 / 60)
MM = int(daysec / 60) % 60
SS = int(daysec % 60)
print(HH,MM,SS)



2015年10月1日 星期四

NodeMCU (ESP8266) 使用紀錄(暫存)

最近入手了塊 WiFi 小板子,使用 ESP8266 模組
NodeMCU官網 紹所描述的如下圖所示,使用方法 超簡單!!!
就如惡夢的開端一樣平凡

===寫在前面===
建議:
1沒有任何程式基礎的別玩這模組,最好有網頁編寫能力(前台 (HTML, JAVAScript)/後台 (Node.js) 都要)
2這模組還算新,各種支援/資源都很欠缺;現有的開發工具很難使用,操作上需要耐心
==========
模塊大小示意
左邊為 50元新台幣 右邊為 1元人民幣

硬體程式更新 
 在板子買來時,應該都預裝了較舊的系統,可以下載較新的來使用
 https://github.com/nodemcu/nodemcu-firmware/releases/tag/0.9.6-dev_20150704
 
 更新程式步驟可以參考 http://bbs.nodemcu.com/t/nodemcu/22 中的
  準備工作
  開始 的 一二步 (第三步用 telnet 進行測試的工作可以先不管)
 
 這一段很重要,必須先學會;因為在後面的操作嘗試過程中,有可能發生因程式錯誤導致模組不斷自我重啟,這時簡單的處理方式就是重新下載硬體程式 (應該也有別的方法,但是沒找到)

軟體操作環境 (NodeMCU Studio 2015)
 在 http://bbs.nodemcu.com/t/nodemcu-studio-ban-ben-geng-xin-wei-build20150111-update-to-version-build20150111/64 下載最新的軟體操作環境
 
 操作環境介紹
   
  共分五個區域 
   紅框-選單 (通常只用來 新增 lua檔案)
   橙色框-對模組進行操作 (下載所選到程式Download 執行所選到程式Execute 模組中的檔案瀏覽Explorer
   綠色框-電腦中的程式列表(此列表為電腦中程式,與模組中的不見得相同)
   藍色框-左邊選到的程式內容會在此區域顯示,可以在這邊做編輯修改,修改後的內容會直接存檔在電腦中
   紫色框-訊息區;像終端機的環境,模塊所返回的訊息會顯示在這邊,也可以直接在這邊下操作命令(注意:這區的操作需要用鍵盤輸入,不可用貼上)

  電腦一開始連接上模組時,訊息區會先跑一段亂碼出來,這沒有辦法避免,之後會顯示硬體程式的版本,若有燒錄了 init.lua 程式,則會自動執行
  
  橙色框的 Explorer ,可打開如下對話框,
  按右邊的 Load 可顯示 NodeMCU 中的檔案,於淡紫色框


硬體介紹
 注意事項寫在前面:
  板子使用 microUSB 5V供電,超過此電壓可能會 
打開異次元通道導致模組損毀
  在ESP8266上面的 GPIO 於 NodeMCU 程式上被重新對應編號,使用時須注意要按照 NodeMCU 的編號來進行操作 
 
 板子所提供的接腳角功能如下圖(左下側方塊表示顏色所對應的 pin 腳功能)
其中 D0 連接板子上的 紅色LED (反向動作,寫 gpio.HIGH 為暗)
   
    10bits ADC  一個
 GPIO     十一個 (除D0外,D1 ~ D10 均可用於 PWM 輸出)
 timer     七個 ( 0 ~ 6 )

程式編輯
 使用的語言是 Lua,不過目前只支援其中一些方法(可能是為了精簡以便在空間很迷你的模塊上實現)

 部分可使用的API介紹 http://bbs.nodemcu.com/t/nodemcu-api/28 (完整的可能須自行到 https://github.com/nodemcu/nodemcu-firmware 下載原始碼來看有加入那些功能)
 
 舉例
 system:
  node.restart() 重啟模塊

  h = node.heap() 返回系統剩餘的程式儲存空間(byte)

 timer:
  tmr.alarm(id, interval, repeat, function do())
  example:
   tmr.alarm(0, 5000, 1, function()
      adv = adc.read(0)    -- read 10bits ad value
   end)
   說明:使用timer0, 每5秒讀取一次ADC的值存放到adv中

 gpio:
  gpio.mode(pin, mode, pullup)
   mode 值:gpio.OUTPUT or gpio.INPUT or gpio.INT(中斷模式)
   pullup 值: gpio.PULLUP or gpio.FLOAT, 預設為 gpio.FLOAT

  gpio.write(pin, mode)
   mode 值: gpio.HIGH or gpio.LOW

  status = gpio.read(pin)
   pin值:0 ~ 11  (D0 ~ D11)

 wifi:
        wifi.setmode(mode)     設定WiFi的使用模式
  可以使用 Station,AP 或 (?) 模式 (wifi.STATION, wifi.SOFTAP, wifi.STATIONAP
  
子模組 wifi.sta:
   wifi.sta.config("ssid","password") 設定連接時要用的 SSID, PASSWORD

   wifi.sta.connect()    透過設定好的 SSID, PASSWORD 連接上AP

   wifi.sta.disconnect()  斷開連接

   ip, nm, gw = wifi.sta.getip()  取得 ip位址,遮罩,預設閘道

  子模組 wifi.ap:
   除 wifi.ap.config 用法要注意引述為 tuple 型別,其他可參考 sta 模塊
    cfg={}
    cfg.ssid="SSID"
    cfg.pwd="password"
    wifi.ap.config(cfg)
  
 net:
  常量 net.TCP, net.UDP
  net.createServer(type, timeout) 創建網頁伺服器. timeout為(sec)

   example:
   sr = net.createServer(net.TCP)  
   sr:listen(80,function(conn)
      conn:on("receive", function(conn, payload) print(payload) end)
      conn:send("hello world")
   end)
  說明:建立網路伺服器, 監聽 prot: 80, 當收到 receive 請求時, 在 訊息區 印出 client 傳來的內容, 並在 client 端網頁上顯示 hello world
 

其他
 HTML 超文件標示語言(英文:HyperText Markup Language,HTML)是為「網頁建立和其它可在網頁瀏覽器中看到的資訊」設計的一種標示語言。
 JavaScript 一種直譯式程式語言,是一種動態型別、基於原型的語言,內建支援類別。它的直譯器被稱為JavaScript引擎,為瀏覽器的一部分,廣泛用於用戶端的腳本語言。
 Node.js 是一個開放原始碼、跨平台的、用於伺服器端和網路應用的執行環境。Node.js應用用JavaScript語言寫成。

 HTTP協議參考:
  http://www.kafan.cn/edu/48002124.html HTTP协议详解
  
 用戶連接網頁時,會送出兩次網頁請求 (當作伺服器的 NodeMCU 於 receive 事件會觸發兩次)

 網頁連接時客戶端會送出請求 要讀取用於網頁抬頭的圖案 favicon.ico , 目前不知道有什麼方法可以下載圖檔到 NodeMCU 中

 一個網頁需要有 HTML HEAD BODY 標記
 
 HTML 中的 input 方法所得的值,會在跟伺服器提出請求時加在資料尾端一起送出(中間隔一空行)

奮戰一周的網頁截圖

2015年8月23日 星期日

Python 學習筆記 - 2 轉換文件編碼 (簡體字 -> UTF-8)

有鑑於上淘寶買的硬體開發板,所附的範例程式都是簡體字編碼,
在繁體中文系統下打開時會顯示成亂碼。
過去是用簡體作業系統打開後另外存成unicode編碼,再拷回繁體系統下使用。
最近嘗試了使用 python 做編碼轉換的動作,以處理亂碼顯示的問題。


2015年8月9日 星期日

Python 學習筆記 - 1


Python 學習筆記-1
2015.8.8

前言:
可以邊寫邊看執行結果的程式語言,開放源碼,網路上有豐富的函式庫支援.
譬如:
 想抓 excel 檔案裡的資料  > 有現成的函式可以支援
 想畫圖表       > 有第三方函式庫
 想使用資料庫     > 有免費的 SQLite

目前網路上可以找到的範例多為 2.x 版,初學會遇到的主要差異在 print 的表示式
      Python 2.x

          >>> print 'being start'

      Python 3.x

          >>> print ('being start')    


安裝環境windows 系統的安裝與使用)

注意:下圖紅圈處要勾選,可以省掉之後自己手動加路徑的麻煩
  

  • 3. 看個人喜好,要將安裝好的程式項目釘選到 開始畫面 還是 工作列

      會用到項目 IDLE (Python GUI)
       

  • 4. 程式執行畫面如下

         
其中 >>>  是命令提示字符,可以在後面輸入要執行的動作
 

建議:

  • 1. 增加檔案總管的右鍵選單,可以直接開啟 command line 模式到該目錄下

                   可以複製以下文字存成 ComPrompt.reg 後,用檔案總管雙擊直接匯入

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Folder\shell\Command Prompt]

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Folder\shell\Command Prompt\Command]
@="cmd.exe /K pushd %L"

  • a. windows 開始處點滑鼠右鍵,選 執行   
                    
  • b. 輸入 regedit [enter]
  • c. 找 HKEY_LOCAL_MACHINE > SOFTWARE > Classes > Folder > shell
                    
  • d. 按滑鼠右鍵 
                             新增  機碼  Command Prompt   (這是會顯示在檔案總管右鍵選單的名稱)     
                            
  • e. 在 Command Prompt 下面再新增一個機碼 Command 
  • f. 在 Command 下面新增一個字串值 
  • g. 輸入字串內容如下
             cmd.exe /K pushd %L
       
  即可在檔案總管下直接開啟該目錄的命令列模式,如下圖: