2018年12月26日 星期三

什麼是 Modbus?


什麼是 Modbus?
  • Modbus是由Modicon公司(現為Schneider的 一個品牌)在1978年提出的
  • Modbus由於易學易用,耗費系統資源極低, 是工業控制領域的一個通訊標準  
  • Modbus 被廣泛應用在 PLC 與 多功能電表等 設備中  
  • 1998年Schneider又推出了TCP/IP乙太網路的 ModbusTCP,使 MODBUS 應用更推向網際 網路。
  • Modbus 是一種需求-回應協定,採用主從架構實作而成。 
  • Modbus允許多個 (大約240個) 裝置連接在同一個網路上進行通訊
    • 舉個例子,一個由測量溫度和濕度的裝置,並且將結果傳送給電腦。在資料採集與監視控制系統(SCADA)中,Modbus通常用來連接監控電腦和遠端終端控制系統(RTU)

網路特性
  • 按電氣特性可分為RS-232、RS-422與RS485。  
  • 按照資料流程的方向可分成兩種基本的傳送方 式:全雙工、半雙工。  
  • RS-485 半雙工通訊由於只需要兩條通訊線, 且通訊距離長,被廣泛用在分散式的控制網路 架構。

MODBUS 協定
  • Modbus協定是主(Master)/僕(Slave)通訊協定; 網路上的每個 Slave 設備必須有唯一的位址(範圍從1到247)
  • 主從架構的通訊作業會成雙成對的出現,必須有個裝置啟動需求並等候回應,也就是說,這個啟動需求的裝置 (主要裝置) 會負責啟動每一次互動。
  • Slave 位址用於定址 Slave 設備,由Master發 起; 位址0用於廣播模式,不需要回應;  
  • 傳輸模式 依照編碼方式可以分為 RTU 與 ASCII模式


MODBUS RTU 模式




  • 使用 16 進制編碼  
  • 使用兩個 Byte 的 CRC 校驗碼  
  • 相較於 ASCII 節省一半的通訊量  
  • CRC校驗遠較LRC運算嚴謹
    • CRC為校驗和的一種,是兩個位元組資料流採用二進制除法(沒有進位,使用XOR來代替減法)相除所得到的餘數。

MODBUS ASCII 模式


  • 封包必須以“ : ”開始,以“CR -LF”結束;  
  • 資料用十六進位 ASCII 碼值表示;  
  • 使用LRC進行錯誤校驗;
    • 將所有位元組相加,捨去進位,然後取2的補數,即為 LRC 的演算法
  • 相較於 RTU 模式可以直接由文字通訊程式進行傳輸

MODBUS TCP
  • IANA (Internet Assigned Numbers Authority:網際網路編號分配管理機構)已為 Modbus協議指配TCP / UDP埠502  
  • Modbus TCP 資料封包包含了MBAP標頭,功能碼和資料三部分
  • MBAP Modbus Application Protocol

Modbus 模擬情境:
  • 像是一個部隊,有一位連長(Master),跟一群大頭兵(slave)
    (Master只有一個.其他都是slave)  
  • 操練中,只有連長(Master)可以說話,大頭兵(slave)不能主動說話,但可以回應。
    (資料的傳送必須由Master開始,slave只是回應。)  
  • 連長可傳送資訊給大頭兵,也可以問大頭兵的狀況
     (Master可以送給slave資料,或是詢問slave的資料) 
  • 大頭兵人多,每個人都有兵籍編號
    (slave 是以站號來區別)  
  • 連長在連集合場講話,或是大頭兵回話,不管連長或大頭兵都聽得到。
    (Master 或Slave 通訊時,每一站都收得到。)

reference:

2018年12月25日 星期二

[MongoDB] C# Driver 時間查詢問題


今天查詢 MongoDB 帶時間條件遇到一個怪問題,
時間條件設定為 2018-12-24T16:00:00Z
但進資料庫查詢時,總是被改成 ISODate("2018-12-24T08:00:00Z")

經一番查詢後,發現 MongoDB driver 在查詢時,
會自動依執行環境的 Time Zone 改成 UTC 時間,
所以才會發生這個怪現象
2018-12-24T16:00:00Z  → time zone (utc+8) → 2018-12-24T08:00:00Z


那該如何解決呢?
var queryDate = new DateTime(2018, 12, 24, 0, 0, 0, DateTimeKind.Utc);
在建立DateTime 時,帶入 DateTimeKind.Utc  ,
即告訴 driver 時間已經是 UTC 時間,
所以不用再幫我轉囉!!
reference: https://stackoverflow.com/questions/19350348/mongodb-c-sharp-driver-and-isodate

2018年12月24日 星期一

如何建立 Aexa Web Service ?


建立 alexa web service 需要以下幾個步驟∶

  • 建立web server (Restful Web API)
  • 建立憑證 (可用私有憑證) 
  • alexa configuration
  • service simulator 

建立web server (Restful Web API)
  • alexa-app: 
    • 已對 alexa voice service 寫好對應的方法及模組,可快速進行開發
    • A Node module to simplify the development of Alexa skills (applications.) 
    • https://github.com/alexa-js/alexa-app

  • alexa-app-server: 
    • 基於上述 alexa-app module 提供 web server 服務,方便開發人員串接 alexa vocie service
    • An Alexa App (Skill) Server module using Node.js and the alexa-app module. 
    • The alexa-app-server module offers a stand-alone web server to host Alexa Apps (Skills). 
    •  Think of it as a simple "container" that allows you to easily publish multiple Alexa Apps with one server. 
    •  This module does not help you write the Alexa Apps (Skills) themselves, as apps are independent modules, written using the alexa-app framework. URL: 
    • https://alexasaturn.tk/alexa/color_picker



建立憑證 (可用私有憑證)

  • Create self-signed certificate語法如下∶
  • 此處要注意一點,必須申請 DNS 並寫入憑證內,才可正常串接服務



alexa configuration
  • Configuration 勾選 Https
  • Default 輸入 URL

  • Self-signed SSL Certificate 
    • 勾選 I will upload a self-signed certificate in X.509 format 
    • 再將憑證內容貼上

service simulator

  • 可用 Test 下的 service simulator 進行測試



Alexa 架構



Alexa 是什麼?

亞馬遜公司所發售Amazon Echo(智慧喇叭)內搭載的智慧型語音助理 - Alexa


Alexa 能做些什麼?

在於「操作顛覆」,其他已上市的 IoT 系統幾乎以「觸控」操作來完成,語音助理 Siri、Google Now 只能做為輔助工具,在 Amazon Echo,以語音為主要操控方式,使用者只靠說話就能與之互動,透過語音下達指令,Alexa 可以為你閱讀新聞、查看天氣與交通狀況,撥流行音樂、確認行事曆、訂Pizza、叫車、買東西等,可說是一款語音助理與生活相互融合的絕佳範例。


開發者可用Alexa Skills Kit 開發自己的Alexa Skill。例如美國最大的餐點外送公司Grubhub在Alexa 上的開頭語是:「Alexa, tell Grubhub I’m hungry」;Uber 則是用:「Alexa, ask Uber to request a ride!」。許多企業都在思考該如何以最直覺的方式讓人們完成點餐、搭車等等的服務,讓消費者更快下決定,有效提高下單率!

架構

  • Framework: alexa-app-server (nodejs) 
  • 溝通需使用 https (self-signed certificate 需參考官方文件) 
  • Backend 主要的對象是 Intent event,依不同的event進行回應 
  • 依需求,溝通過程不主動關閉 session 需在8秒內回應 response,否則將被強制關閉 session


Intent 範例



2018年12月23日 星期日

什麼是 RS485?

什麼是 RS-422?

RS-422 (EIA RS-422-A 標準) 為過去用於 Apple Macintosh 電腦的序列連結。 與 RS-232 參照至接地的非平衡式訊號相反,RS-422 為使用差動電子訊號, 差動傳輸使用 2 個通道,分別用於傳輸與接收訊號,因此相較於 RS-232,其抗擾性更佳,通訊距離也更長。 這些優勢讓 RS-422 更適合用於工業級應用。


什麼是 RS485?

RS-485 (EIA-485 標準) 為 RS-422 的改良版本,從原本的 10 組裝置提高至 32 組裝置,並定義必要的電子特性,以在最大負載下保持適當的訊號電壓。

RS232 連線長度只能50~100 呎(17~33m),一個 Comm Port只能接一台,為因應工廠控制需要,於1993年訂定 RS485

  • 抗雜訊能力提高
  • 距離可達4000 呎 (1333 米) 
  • 同時可控制32個設備
  • 優點 
    1. 比RS232便宜,只使用一個+5V電源, 比RS232用的 ±5V方便 
    2. 網路功能:可長距離、多儀器連結,使用高阻抗的接收器,可接達256 台
    3. 長距離: 1333m
    4. 快速:可達10Mbits/s
      (RS232只能達 ~20Kbits/s)
  • RS485接線法,基本上只有三條線 TRA, TRB, SG 可只使用2線, 須加終端電阻, 每台機器須設不同的位址
  • 終端電阻加在電腦端及最遠一台機器的一端,需搭配導線的阻抗值 (必須大於75ohm),一般而言AWG24線使用(100~150ohm即可)
  • 由於RS232還是PC現有的介面,所以常使用RS232到RS485的轉接器,以便利用RS232控制RS485儀器

什麼是 RS232C?


什麼是 RS232C

RS-232 (ANSI/EIA-232 標準) 為過去 IBM 相容電腦的序列連結功能, 可用以連接滑鼠、印表機或數據機,或用於工業級儀器控制等許多功能。
  • 電腦中最常用的介面之一。 
  • RS-232 : Recommend Standard number 232. 
  • C 表示最新的版本. 
  • 大多電腦都是符合RS-232C一部份標準. 
  • 連線長度只能50~100 呎(17~33m)
  • 一個 Comm Port只能接一台
  • 全功能的 RS-232C 規定使用25-pin D 接頭,使用其中的 22 pins. 
  • 對電腦通訊,大多是不必要的,因此大多數PC只使用一個9pin的公接頭。 
  • 其實,只要使用其中3根pin便可達到全雙工 (full duplex)通訊的目的,一根Send,一根 receive,一根ground
    (Full duplex:送資料與接收資料同時進行,亦即是 雙向的溝通bi-directional)

RS232定義兩種接頭形式,接腳訊號定義不同
  • DCE (data communication Equipment) 
    • 母接頭
    • 資料通訊設備→遠端儀器
  • DTE (data terminal equipment) 
    • 公接頭
    • 資料終端設備→電腦
  • DTE 與DCE可直接一對一連接,
  • 同類間連接需要用Null modem Cable,交換 send 與 receive腳位 

資料如何傳輸 - start bit
  • RS232是屬於序列式的(serial)傳輸資料,資料是一個bit一個bit傳
  • 一般狀態,TD 與RD是在高電位,一端的TD 是接到另端的RD,當有資料要傳時,一 端的TD會先被拉低電位,而另一端的 RD接收到低電位開始接收資料,這個動作叫做送起始位元( Start bit)

接收資料-data bits
  • Start bit後,兩邊的設備開始準備接收資料 
  • 為了溝通,兩邊必須有相同的傳輸速度(baud rate),及有多少 data bits要送
    (Baud rate: 每秒多少bit的傳輸動作)
  • 確定好傳輸速度,接著規定要傳多少bit, 一般是傳8或7 bit,以8 bit最常用。LSB最小位元先送。

資料檢查 Parity bit 
  • 檢查序列資料是否傳得正確?
  • 奇偶檢查 
  • Data bit送完,會再送一個parity bit,讓接收端檢查資料是否正確
  • 有以下幾種: 
    • none:不送parity bit (最常用) 
    • Odd:當data bit有偶數個1時 → 送1補成奇數個 
    • Even :當data bit有奇數個1時 → 送1補成偶數個 
    • Mark:永遠送1做parity bit 
    • Space :永遠送0做parity bit

Stop Bit
  • 停止位元: 將電位拉高,宣告資料已經傳 輸完畢。 
  • 最常用的傳輸格式常記為 8-N-1 8: 
    • 8 data bit 
    • N: No parity bit 
    • 1: 1 start/stop bit
      (設備較慢時用 2bits)

防止資料遺失
  • 使用Handshaking(握手 ) 
    • 可不用 
    • 很多方式
      • 利用某一根線的高低電位 ( 如DTR),當一端準備收資料時先拉高某一線電位,另一端接收到訊息後,才開始送資料
      • 利用TD, RD線,傳送特殊的byte 當成準備接收資料的代號
  • 使用中斷(interrupt)或詢問(polling) 
    • Interrupt:有事件發生時執行 
    • Polling:以軟體不斷檢查資料
  • 使用Acknowledgement(確認 ) 
    • 收到資料時,送回一個特殊byte確認資料收到
  • 錯誤檢查(error checking) 送checksum byte給接收端檢查資料正確性,有問題,通知重送資料

2018年12月10日 星期一

ASP.NET Core 2.0 - JwtBearerEvents


想在 .Net Core 2.0 裡接 jwt 驗證的事件,
比如拿到 token 驗證失敗的 exception,
該怎麼做呢?

建立 CustomJwtBearerEvents 類別,實作 JwtBearerEvents
public class CustomJwtBearerEvents : JwtBearerEvents
{
    private static Logger _logger = LogManager.GetCurrentClassLogger();

    public CustomJwtBearerEvents() : base()
    {}

    public override Task AuthenticationFailed
            (AuthenticationFailedContext context)
    {
        _logger.Error(context.Exception.Message);
        return this.OnAuthenticationFailed.Invoke(context);
    }

    public override Task TokenValidated(TokenValidatedContext context)
    {
        _logger.Trace("OnTokenValidated: " + context.SecurityToken);

        if (something)
        {
            var failMsg = $"Invalid API Token : {jwtToken.RawData}";
            context.Fail(failMsg);
            _logger.Error(failMsg);
                    
        }
        return this.OnTokenValidated.Invoke(context);
    }

    public override Task Challenge(JwtBearerChallengeContext context)
    {
        return this.OnChallenge.Invoke(context);
    }

    public override Task MessageReceived(MessageReceivedContext context)
    {
        return this.OnMessageReceived.Invoke(context);
    }
}

reference: https://www.codeproject.com/Articles/1205160/ASP-NET-Core-Bearer-Authentication

2018年3月28日 星期三

Runtime + Compiler on Vue-Cli 3.0


有需求動態載入 component,
在 jsbin 做簡單的測試是沒問題,
但使用 Vue-Cli 3.0 的開發環境,
卻拋出以下錯誤

You are using the runtime-only build of Vue where the template compiler is not available. Either pre-compile the templates into render functions, or use the compiler-included build.

經一番奮鬥後,發現 Vue-Cli 3.0 的 webpack 設定,
預設載入的 Vue 是 vue.runtime.esm.js,
所以在 runtime 的時候會發生此問題,
需將  vue.runtime.esm.js 換成  vue.esm.js
在 run time 期間也有 compiler 可以用

那該怎麼做呢?

在根目錄下設定 vue.config.js 如下即可
 (若沒有此檔,請自行新增!)
module.exports = {
  configureWebpack: {
    resolve: {
      alias: {
        'vue$': 'vue/dist/vue.esm.js'
      }
    }
  }
}


參考來源:

  1. https://github.com/vuejs/vue/tree/dev/dist#explanation-of-build-files
  2. https://github.com/vuejs/vue-cli/blob/dev/docs/webpack.md

2018年3月22日 星期四

關閉 Visual Studio 2017 自動編譯 ts 檔


在專案檔加入 <typescriptenabled>true</typescriptenabled>.

  <PropertyGroup>
    <TargetFramework>netcoreapp2.0</TargetFramework>
    <TypeScriptCompileBlocked>true</TypeScriptCompileBlocked>
  </PropertyGroup>


reference:

TypeScriptCompileBlocked

If you are using a different build tool to build your project (e.g. gulp, grunt , etc.) and VS for the development and debugging experience, set true in your project. This should give you all the editing support, but not the build when you hit F5.

2017年12月14日 星期四

Startup pm2 command for Windows Server 2012 R2


需在 windows server 重新啟動的時候,
自動執行 pm2 start someapp.js,
pm2 有 startup command 提供此機制,但不支援 windows,
以下是 worked solution


The following is my latest solution which works really well:
  • create a specific Windows user for running node scripts
  • login as that user and npm install pm2 -g
  • pm2 start all the apps I would like to have startup
  • pm2 save to save the current process list
  • create a .bat file and within it paste the following commands:
@echo off
set HOMEDRIVE=C:
set HOMEPATH=\Users\%USERNAME%
set path=C:\Users\%USERNAME%\AppData\Roaming\npm;%path%
pm2 delete all & pm2 resurrect

Use Windows Task Scheduler to create a task that:
  • runs "whether user is logged on or not"
  • is Triggered "At startup"
  • is configured to run the .bat file that we created


2017年11月7日 星期二

How to enable hardware virtualization on a MacBook?

開發環境在 Mac 上的 windows 10 Home
需要啟用 virtualization ,
可是硬體本身有支援,卻沒有啟用 virtualization,
但是該如何啟用呢?
方式如下:

How to enable virtualization in Boot Camp.
  1. holding the option key on startup, boot in to OS X. 
  2. Then go to System Preferences 
  3. Startup Disk and choose your Boot Camp partition
  4. The computer will restart and boot into Windows, with virtualization enabled.

OK! 附張成功的圖紀念一下!

2017年11月1日 星期三

Error: The 'Microsoft.ACE.OLEDB.12.0' provider is not registered on the local machine.

使用 LinqToExcel 突然發生 error,原來是安裝 windows update 後,發生的慘案
Error: The 'Microsoft.ACE.OLEDB.12.0' provider is not registered on the local machine.

解決方案如下:

1. uninstall KB4041676 on Windows 10 and KB4041681 on Windows 7.

2. Find prior version (4.0.9801.0) of msexcl40.dll

3. Place in another directory. They suggest the application directory, but since in the next step you will modify registry to point to this older version, it can probably go anywhere.

4. Update registry key HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Jet\4.0\Engines\Excel\win32 to point to the location from step 2.

但此招是救急,可能有安全性的疑慮!

2017年10月16日 星期一

query pagination data with mongoose


目前透過 mongoose 查詢 pagination 資料覺得很麻煩,
先取得 total count 再取 page data,
目前使用的方式如下:

    user
        .find(where)
        .count()
        .then((totalCount) => {
            if (totalCount && totalCount > 0) {
                return user.find(where)
                    .select('field1 field2 field3 filed4')
                    .sort({ createdOn: -1 })
                    .skip(skip)
                    .limit(limit)
                    .exec()
                    .then((rows) => {
                        return {
                          rows:rows
                          totalCount: totalCount
                    });
            } else {
                 return res.status(200)
                        .json({
                         rows: [],
                         skip: skip,
                         limit: limit,
                         totalCount: 0
                        })
                        .end();
            }
        })
        .then((result) => {
                 return res.status(200)
                        .json({
                         rows: result.rows,
                         skip: skip,
                         limit: limit,
                         totalCount: result.totalCount
                        })
                        .end();
        })
        .catch((err) => {
            next(err);
        });

寫得落落長,太麻煩了,花了一些時間查查,有沒有什麼方便的方式
原來 mongoose 有 pagination plugin 可以用,真的是佛心來的,
使用方式如下:

Installation:
npm install mongoose-paginate

Usage:
var mongoose         = require('mongoose');
var mongoosePaginate = require('mongoose-paginate');
 
var schema = new mongoose.Schema({ /* schema definition */ });
schema.plugin(mongoosePaginate);
 
var Model = mongoose.model('Model',  schema); // Model.paginate() 

Model.paginate([query], [options], [callback])

所以上面的範例可以改成:
var where   = {};
var options = {
    select:   'field1 field2 field3 filed4',
    sort:     { createdOn: -1 },
    lean:     true,
    offset:   20, 
    limit:    10
};
user.paginate(where, options).then(function(result) {
    return res.status(200)
                        .json({
                         rows: result.docs,
                         skip: skip,
                         limit: limit,
                         totalCount: result.total
                        })
                        .end()
});

太好了,是不是簡單很多!

reference:https://www.npmjs.com/package/mongoose-paginate

Avoiding Callback Hell in Node.js - Promise


寫 nodejs 就會用到非同步的 callback
就會碰到所謂的「callback hell」的囧境
什麼是 callback hell? 如下所示:

doSomeAsyncFunc(function () {
  doSomeAsyncFunc(function () {
    doSomeAsyncFunc(function () {
      doSomeAsyncFunc(function () {
        doSomeAsyncFunc(function () {
          doSomeAsyncFunc(function () {
            doSomeAsyncFunc(function () {
              doSomeAsyncFunc(function () {
                doSomeAsyncFunc(function () {
                  // 我到底在第幾層地獄啊!?
              })
            })
          })
        })
      })
    })
  })
})



這樣光要看懂就很辛苦了,還要怎麼維護程式碼呢?

有幾種解決方式:

  1. async.waterfall
  2. promise
  3. async/await

上一篇介紹了 async.waterfall,現在來看看 Promise 如何使用

1. 先將 doSomeAsyncFunc 包裝成 promise 物件
doSomeAsyncFunc(function () {
  return new Promise(function(resolve, reject) {
    // do something, possibly async
    if (/* everythings fine */) {
      resolve(result);
    } else {
      reject(err);
    }
  });
}

2. 使用 primise.then 即可攤平 callback hell

var promise = doSomeAsyncFunc();
promise.then((result) => {
  // get result
  return '2';
}).then((result2) => {
  // get result2 ('2')
  return '3';
}).then((result3) => {
  // get result3 ('3')
}).catch((err) => {
  // error handling
});

3. 所以一開始的範例就可以改成:

var promise = doSomeAsyncFunc();
promise.then((result) => {
  // do something
  return doSomeAsyncFunc();
}).then((result) => {
  // do something
  return doSomeAsyncFunc();
}).then((result) => {
  // do something
  return doSomeAsyncFunc();
}).then((result) => {
  // do something
  return doSomeAsyncFunc();
}).then((result) => {
  // do something
  return doSomeAsyncFunc();
}).catch((err) => {
  // error handling
});

這樣就可以攤平可怕的 callback hell,回到地球表面囉!

2017年9月26日 星期二

Avoiding Callback Hell in Node.js - async.waterfall


寫 nodejs 就會用到非同步的 callback
就會碰到所謂的「callback hell」的囧境
什麼是 callback hell? 如下所示:

doSomeAsyncFunc(function () {
  doSomeAsyncFunc(function () {
    doSomeAsyncFunc(function () {
      doSomeAsyncFunc(function () {
        doSomeAsyncFunc(function () {
          doSomeAsyncFunc(function () {
            doSomeAsyncFunc(function () {
              doSomeAsyncFunc(function () {
                doSomeAsyncFunc(function () {
                  // 我到底在第幾層地獄啊!?
              })
            })
          })
        })
      })
    })
  })
})


這樣光要看懂就很辛苦了,還要怎麼維護程式碼呢?

有幾種解決方式:

  1. async.waterfall
  2. promise
  3. async/await


先來看看 async.waterfall 如何解決問題

步驟如下:

1. 先安裝 async package :   $ npm install --save async

2. import async package :   var async = require("async");

3. waterfall(tasks, callback) 的說明:

Runs the tasks array of functions in series, each passing their results to the next in the array. However, if any of the tasks pass an error to their own callback, the next function is not executed, and the main callback is immediately called with the error.

簡單來說,只要 error 的參數是 null ,就會一直往下丟 callback,
若中途呼叫 callback 且 error 參數不為 null ,則直接進入 mail callback

範例:
async.waterfall([
    function(callback) {
        callback(null, 'one', 'two');
    },
    function(arg1, arg2, callback) {
        // arg1 now equals 'one' and arg2 now equals 'two'
        callback(null, 'three');
    },
    function(arg1, callback) {
        // arg1 now equals 'three'
        callback(null, 'done');
    }
], function (err, result) {
    // result now equals 'done'
});

也就是說,一開始的 callback hell sample 可以改成:
async.waterfall([
    function(callback) {
        doSomeAsyncFunc1(function (error, result) {
            callback(error, result);
        });
    },
    function(callback) {
        doSomeAsyncFunc2(function (error, result) {
            callback(error, result);
        });
    },
    function(callback) {
        doSomeAsyncFunc3(function (error, result) {
            callback(error, result);
        });
    }
    ......
], function (err, result) {
    // main callback 
    if (err) {
        // do something
    } else if {
        // do something
    }
});

這樣就可以攤平可怕的 callback hell,回到地球表面囉!

reference: https://caolan.github.io/async/docs.html#waterfall

2017年8月9日 星期三

MySQl Error: Data too long for text column


近期站台在塞資料時,
 MySQL 拋出以下錯誤:

Error Message:
Data too long for column 'xxxx' at row 1

發現要塞 80k 資料進 text 型別的欄位失敗了!
看來是跟 MSSQL 的設計不同 ( 我是從 MSSQL 遷徙過來的 )
為了得到正確的觀念,查了一下 MySQL TEXT 欄位的定義
原來 MySQL 還有對 Text 再做細分,如下:

      Type | Maximum length
-----------+-------------------------------------
  TINYTEXT |           255 (2 8−1) bytes
      TEXT |        65,535 (216−1) bytes = 64 KiB
MEDIUMTEXT |    16,777,215 (224−1) bytes = 16 MiB
  LONGTEXT | 4,294,967,295 (232−1) bytes =  4 GiB

以後要用 TEXT 欄位,還是要多注意實際情況選擇正確的型別囉!

2017年8月8日 星期二

讀書心得:如何設計好網站


近期一直困擾著什麼樣的操作方式對 user 才是好的,

之前一直覺得好不好用應該問使用者,
請使用者提出一些意見或想法,
但使用者幾乎不可能提出什麼好的想法,
亨利福特曾說:如果當年去問顧客要什麼,他們肯定會回答我:給我一匹更快的馬

所以找看看有沒有什麼幫助的書,
找到了這本覺得不錯,分享給各位

書名:如何設計好網站:Dont Make Me Think
ISBN:9789863750086


簡單分享一下心得:

  1. 別讓 user 動腦去想
    • 這絕對也是最重要的易用性規則,不用動腦就知道怎麼用,就對了
  2. 使用者看網頁,是用掃視、矇著用的
    • 使用者上網站,大致掃一遍網頁,看到有興趣的就點進去,不會從頭到尾看完的
  3. 省略不必要的贅字
    • 作者建議一段文字,先篩選掉 1/3 後,再篩選掉 1/3,這樣就差不多了
  4. 麵包屑很重要,讓 user 知道人在何處
  5. 每頁都應該有固定的地方,可以回到首頁
    • 如:左上方的 logo,當user迷路時,可以有重新開始的機會
  6. 易用性測試
    1. 場地:二間會議室
    2. 參與人員:受測者,陪測者,觀測者
      1. 受測者,作者建議不要找相關領域,因為是不是相關領域根本不重要,
      2. 專家級的使用者,不會介意多幾個清楚的說明
    3. 週期:一個月一次
      1. 如:每月第四週星期三上午
    4. 什麼時候開始測?
      1. 開發前就可以開始測
      2. 建立簡單的雛型就可以測
      3. 沒有雛型,那就測競爭對手的網站
    5. 情境:
      1. 聘請相關或不相關領域的受測者,進行功能操作,
        會有一名陪測員說明系統及測試的任務,如:建立版型,版型發佈等等,
      2. 陪測員不能刻意引導受測者
      3. 受者測操作時,需大聲說出目前的想法,如:怎麼這麼難用!
      4. 在測試的 pc 上安裝螢幕分享軟體(含使用者的聲音、滑鼠位置等等),
        同步給另一間會議室的主管、RD相關人等觀察
      5. 觀察者在觀察時,同步記綠發現的問題,並將紀錄到的問題排列優先順序( 投票等等 ),
        ps:可能會有異想不到的發現喔!
      6. 處理的問題量及難度,要可以在下次測試前改完,不可太多
  7. 利用易用性測試,擺脫討論不完的爭論
    • 例如:在勾選某類型資料時,要使用下拉選單還是 checkbox list,
    • 這種每個人都有不同的經驗及偏好,這是爭論不完又浪費時間的;


當然還有其他細節我沒有提到,有興趣的話,可以看看這本書囉!

2017年8月2日 星期三

Gmail Error handling: 5.5.1 Authentication Required


透過 Gmail SMTP 發信,卻遇到以下錯誤訊息:

Gmail Error :The SMTP server requires a secure connection or the client was not authenticated. The server response was: 5.5.1 Authentication Required

原因:
因為 google 會檢查帳戶平時的使用狀態並做一些保護機制,平時登入地點是在固定地方,但若今天帳戶要設定在 VM 上,而 VM 在別的區域,那 google 會判定帳戶有風險,於是會鎖住登入的那台 server,並拋出這個 exception

解決方式:
在被鎖住的 server ,透過網頁登入 gmail,此時 gmail 會問你一些安全性問題,進行設定後,即可正常收發信件了!

reference: https://stackoverflow.com/questions/20906077/gmail-error-the-smtp-server-requires-a-secure-connection-or-the-client-was-not


2017年6月5日 星期一

IoT Platform Protocol



最近整理了一下,
各IoT平台會用到的 protocol,
看起來 MQTT 已被每個平台拿來使用,
要走 IoT 這塊,MQTT 已是必學的技術了!


Azure
  • AMQP
  • MQTT
  • HTTP
  • MQTT over WebSocket
  • AMQP over WebSocket
AWS
  • MQTT
  • WebSocket
  • HTTP
Google Cloud
  • MQTT
  • HTTP
IBM's Watson IoT Platform
  • MQTT, 
  • HTTP
中華電信智慧聯網平台
  • MQTT, 
  • WebSocket 
  •  HTTP



2017年3月3日 星期五

Renaming web site in IIS


遇到實務上的需求,
先架設測試站台 ( TestWebSite ),
確認無誤後需要轉換正式站台 ( ProdctionWebSite ),
但是.....
在 IIS 下,web site 如何更名?


在一番搜尋及實驗後,使用 appcmd 可以滿足此需求
步驟:

  1. 開啟 command 進入此路徑:
    C:\Windows\SysWOW64\inetsrv
  2. 輸入 appcmd list app :會列出目前 IIS 上的 WebSite
    appcmd list app
    
    APP "Default Web Site/" (applicationPool:DefaultAppPool)
    APP "Default Web Site/production1" (applicationPool:mypool)
    APP "Default Web Site/test1" (applicationPool:mypool)
  3. 輸入 appcmd set app [app name] -path [new name]
    appcmd set app "Default Web Site/production1" -path:/oldproduction
    appcmd set app "Default Web Site/test1" -path:/production1
  4. 輸入 appcmd list app,確認修改結果
    appcmd list app
    
    APP "Default Web Site/" (applicationPool:DefaultAppPool)
    APP "Default Web Site/oldproduction" (applicationPool:mypool)
    APP "Default Web Site/production1" (applicationPool:mypool)

參考:http://stackoverflow.com/questions/5687057/renaming-applications-in-iis-7-0