2017年11月10日 星期五

AngularJS 使用 $routeProvider 時輸出路徑 "/" 變更成 "%2F" 解決方式

按照 AngularJS 官方網站實做了 Wire up a Backend 的範例發現了一些問題,主要是在 routeProvider 變更瀏覽器 URL時,路徑上的 "/" 被改成了 "!/" 與指定路徑 "/new" 被換成 "%2Fnew",導製後續動作都無法解析問題:


按照它的範例執行一開始路徑就怪怪的,當按下『Add』時,沒有切換到 detail.html 的畫面,原因在於路徑出現了非預期的字元。


這個原因出在 routeProvider 回傳時把一些特殊字元進行轉換造成的問題,因此必須修改它的 config 對 routeProvider 處理程式碼片段:
(原程式碼)

.config(function($routeProvider) {
  var resolveProjects = {
    projects: function (Projects) {
      return Projects.fetch();
    }
  };

  $routeProvider
    .when('/', {
      controller:'ProjectListController as projectList',
      templateUrl:'list.html',
      resolve: resolveProjects
    })
    .when('/edit/:projectId', {
      controller:'EditProjectController as editProject',
      templateUrl:'detail.html',
      resolve: resolveProjects
    })
    .when('/new', {
      controller:'NewProjectController as editProject',
      templateUrl:'detail.html',
      resolve: resolveProjects
    })
    .otherwise({
      redirectTo:'/'
    });
})

修改:增加 $locationProvider.hashPrefix(''); 可以讓顯式的URL正確顯示
(修改後)

.config(function($routeProvider,$locationProvider) {
  var resolveProjects = {
    projects: function (Projects) {
      return Projects.fetch();
    }
  };
  $locationProvider.hashPrefix('');
  $routeProvider
    .when('/', {
      controller:'ProjectListController as projectList',
      templateUrl:'list.html',
      resolve: resolveProjects
    })
    .when('/edit/:projectId', {
      controller:'EditProjectController as editProject',
      templateUrl:'detail.html',
      resolve: resolveProjects
    })
    .when('/new', {
      controller:'NewProjectController as editProject',
      templateUrl:'detail.html',
      resolve: resolveProjects
    })
    .otherwise({
      redirectTo:'/'
    });
})




比較弔詭的是 hashPrefix 是用來設定 URL上#後面的前綴字元用的

理論上沒有指定  hashPrefix('!') 理論上URL不應該出現  /#!/  這樣的狀況

而且 / 被 URI 編譯成 %2F 的問題也不知為何?

當然強制 hashPrefix('') 不是問題,但卻一併處理了 URI 編碼問題?怎麼看都像是個BUG吧!!

關於hashPrefix的用法可以參考這邊 http://code-beginner.logdown.com/posts/334029-start-angularjs-theme-routing

官方網站的範例卻可以在官方網站正常執行,在我的網站卻不行正常有點奇怪,而且我也嘗試過各種瀏覽器都是一樣的狀況。










2017年11月9日 星期四

OA辦公椅越坐越下沉問題

一般的公司辦公室的辦公椅大概都是長成這樣子的:


搭配的辦公桌通常是固定的高度,大家都一樣高,

因此只能調整座椅的高度,而OA辦公椅因為要符合各種人身高需求,

通常但是這種椅子的結構很多種,但它的升降機構但最常見(也最便宜)的就是像螺絲一樣利用旋轉支柱來改變高低的。


但這種旋轉調整高低的椅子卻有一個很糟糕的問題,因為大部分坐OA椅的人會音工作需要旋轉椅子改變方向,但是如果沒有將這個螺旋固定住,久會導致椅子越坐越低,不知不覺坐姿改變,導致肩膀痠痛或是腰酸背痛。

總之,這種升降機結構就是一個『爛東西』,但有的廠商會稍微貼心點在旋轉柱上加上一個固定用螺絲,可以用來鎖住調整好的位置。

如果,你的公司只有這種OA椅給你用,然後也沒得選擇,你可以用點小技巧來固定椅子的高度。

只要利用束帶就可以了,找兩條(一條固定不太住)足夠長的束帶,調整好椅子高度後再稍微調高 一 ~ 二 格螺紋高度後再把束帶綁入螺紋的溝槽內(一定要綁入溝槽內,不然會滑脫),然後用老虎鉗子把束帶拉緊(如果只用手的力量束帶綁不太緊),如下:

使用一段時間後,位置只會有一點往上跑,只時再坐一次調整(再綁入一條束帶)固定住,就不會跑掉了。

2017年10月30日 星期一

Xamarin : Android : Vibrate 使用裝置震動

在 Xamarin 下開發 Android 裝置需要振動程式碼如下


void button_vibrator_Click(object sender , EventArgs ea)
{
    // 建立振動服務
    var vibrator = (Vibrator)GetSystemService(Android.Content.Context.VibratorService);
    int iDuration = 500; // 500毫秒,振動持續時間
 
    // 執行
    vibrator.Vibrate(iDuration);
}


這個 Vibrator 需要引用


using Android.OS;



這個服務屬於非同步機制,發出震動後不會等待振動時間完畢,而會繼續執行程式。

另外,還需要賦予適當的使用權限,可以在專案屬性調整


或是到 AndroidManifest.xml 裡增加


<uses-permission android:name="android.permission.VIBRATE" />


建議使用專案屬性調整會比較安全,比較不會打錯字

2017年10月28日 星期六

Xamarin : Android : playback a tone 發出警告聲(簡單聲音)

在 Xamarin 下開發 Android 讓裝置發出 警告聲音 或是 提示聲音


void button_beep_Click(object sender , EventArgs ea)
{
    int iVolume = 100; // 0 ~ 100 音量,但不是裝置實際音量,而是產生音波的音量
    int iDuration = 500; // 500毫秒,聲音持續時間
    // 建立執行物件
    var tonGen = new ToneGenerator(Android.Media.Stream.Music, iVolume);

    //播放聲音
    //tonGen.StartTone(Android.Media.Tone.CdmaAlertAutoredialLite,1000);
    //tonGen.StartTone(Android.Media.Tone.CdmaAlertCallGuard, 200);
    //tonGen.StartTone(Android.Media.Tone.CdmaAlertIncallLite, iDuration );
    //tonGen.StartTone(Android.Media.Tone.CdmaAlertNetworkLite, iDuration );
    tonGen.StartTone(Android.Media.Tone.PropBeep, iDuration );
}


Android.Media.Tone 底下列舉不少基本 DTMF 的音調,可以自行選擇測試
這個元件比較適合播放訊息聲音(比較簡單的音調)。

如果要播放音樂建議使用 AudioTrack 物件。

注意這個播放是屬於非同步的,而且會以最後一次呼叫StartTone的聲音為主,如果同時播放多個聲音檔,則只會聽到最後一個聲音。


2017年10月27日 星期五

Xamarin : Android : Lock Screen(View) Orientation 禁止螢幕(畫面)旋轉

在 Xamarin 開發 Android 的時候如果要禁止畫面旋轉 要在 Activity 的程式碼使用下面方式(黃色部分)宣告


[Activity(Label = "ZxingTest", MainLauncher = true, Icon = "@drawable/icon" ,ScreenOrientation =Android.Content.PM.ScreenOrientation.Portrait)]


Android.Content.PM.ScreenOrientation 裡面有些列舉屬性,像是:
Android.Content.PM.ScreenOrientation.Portrait (豎屏;直向畫面)
Android.Content.PM.ScreenOrientation.Landscape (橫屏;橫向畫面)

而大部分網路上說修改 AndroidManifest.xml 裡面更改
<activity> 屬性增加 android:screenOrientation="portrait"等這類方式都是
 Android Studio 的開發方式 不是 Ms Visual Studio 的開發方式,所以特別紀錄一下。


為什麼要禁止螢幕旋轉:

除了特定版面排版特性之外,當每次旋轉螢幕時 Activity 和 View都會被重載 (Reload/Redraw) ,此時畫面上所有物件都會被 摧毀並釋放記憶體空間,由於這個特性,在畫面上的資料如果沒被儲存就會消失的一乾二淨。

當然可以利用 OnSaveInstanceState 和 OnRestoreInstanceState 事件覆寫來處理資料儲存和還原,但是如果不想做太複雜,就直接設定禁止畫面旋轉就可以了。

2017年10月25日 星期三

Xamarin : Android : Using ZXing.Net.Mobile Scan Barcode 掃描讀取條碼/QR碼

網路上大部份文章在講 Xamarin 開發都用上了 CPL類型的專案,
對於純粹使用 Android 專案使用者要理解真是有點不方便,

這裡是記錄了在 Xamarin 下的 Android 專案如何開發一個讀取 條碼或是 QR碼的功能

個功能是基於 ZXing.Net.Mobile 套件開發的,可以自行把這個套件應用你的專案中

1、假設你經開啟了一個 Android blank Project (空白專案)

2、使用 NuGet 管理員去新增 ZXing.Net.Mobile 套件,並把它安裝到專案中


3、然後到你要呼叫使用 ZXing 操作的 Activity 去新增引用(在這案例裡我是放在 MainActivity.cs 內)

using ZXing;
using ZXing.Mobile;


4、在顯示畫面(Main.axml)上設計兩個 TextView 和一個 Button,用來啟動掃描和接收掃描的結果


5、然後就是把操作 ZXing 的程式碼加入,在這案例中,我只簡單全部做在 MainActivity 的 OnCreate 內,實際應用上你可以依照需要放置。

using Android.App;
using Android.Widget;
using Android.OS;
using ZXing;
using ZXing.Mobile;

namespace ZxingTest
{
    [Activity(Label = "ZxingTest", MainLauncher = true, Icon = "@drawable/icon")]

    public class MainActivity : Activity
    {
        //建立操作物件指標
        private TextView _barcodeFormat, _barcodeData;

        protected override void OnCreate(Bundle bundle)
        {
            base.OnCreate(bundle);

            // 設定顯示畫面
            SetContentView (Resource.Layout.Main);

            //掃描元件初始化
            MobileBarcodeScanner.Initialize(Application);

            //簡化操作的位置(變數指標)
            _barcodeFormat = FindViewById<TextView>(Resource.Id.barcode_format);
            _barcodeData = FindViewById<TextView>(Resource.Id.barcode_data);

            //建立按鈕 Click 事件
            var button = FindViewById<Button>(Resource.Id.button_scan);
            button.Click += async (Senders, args) =>
            {
                //設定掃描元件操作
                var opts = new MobileBarcodeScanningOptions
                {
                    //限定(啟用)可掃描識別種類
                    PossibleFormats = new System.Collections.Generic.List<BarcodeFormat>
                    {
                        BarcodeFormat.CODE_128,
                        BarcodeFormat.CODE_39,
                        BarcodeFormat.EAN_13,
                        BarcodeFormat.EAN_8,
                        BarcodeFormat.QR_CODE
                    }
                };
                //建立可執行化實例
                var scanner = new MobileBarcodeScanner();
                //利用 await 執行掃描,等待回應
                var result = await scanner.Scan(opts);

                //將回傳結果輸出到 TextView
                _barcodeFormat.Text = result?.BarcodeFormat.ToString() ?? string.Empty;
                _barcodeData.Text = result?.Text ?? string.Empty;
            };
        }
    }
}


6、實際操作
主畫面


掃描


返回掃描結果


參考文章來源:
Xamarin Android 二维码扫描示例– Design based .NET

2017年10月19日 星期四

C# AES encrypt/decrypt and Base64 encode/decode

範例檔案: 這裡下載
純執行檔:這裡下載

有興趣研究 AES 加解密 與 Base64 編解碼 的可以研究一下
因為用到了AES 元件,所以只適用 .NET 3.5 以上

畫面如下:

為什麼 AES 和 BASE64 寫在一起?
因為 AES 加密後的內容是 ASCII 碼,很多是無法以明文顯示的,因此會再編碼成BASE64以便傳遞或攜帶。反過來說,接收到AES的密碼通常會以BASE64編成居多,所以必須解碼後再進行AES解密環原本文。


Base64編碼:
要引用 using System;

//將文字內容(明文)轉成base64文字(編碼)
tbB64_2.Text = Convert.ToBase64String(Encoding.Default.GetBytes(tbB64_1.Text));

Base64解碼:
要引用 using System;

//將base64編碼文字轉回明文(解碼)
tbB64_1.Text = Encoding.Default.GetString(Convert.FromBase64String(tbB64_2.Text));

AES加密:
要引用 using System.Security.Cryptography;

static byte[] EncryptionByAES(string plainText, byte[] key, byte[] IV)
{
  byte[] encrypted;
  //檢查參數
  if (plainText == null || plainText.Length <= 0)
     throw new ArgumentNullException("沒有要加密的文字");
  if (key == null || key.Length <= 0)
     throw new ArgumentNullException("沒有提供金鑰");
  if (IV == null || IV.Length <= 0)
      throw new ArgumentNullException("沒有提供IV");
  //這裡使用Aes創建編譯物件
  using (Aes aes = Aes.Create())
  {
      aes.Key = key;
      aes.IV = IV;

      //創建密碼編譯轉換運算
      ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV);
      //使用記憶體串流來儲存結果,
      //如果要使用byte來儲存,就必須先提供byte[]空間長度 encryp = Convert.FromBase64String(plainText);
      using (MemoryStream mEncrypt = new MemoryStream())
      {
           //使用CryptoStream創建編碼轉換方法
           using (CryptoStream cEncrypt = new CryptoStream(mEncrypt, encryptor, CryptoStreamMode.Write))
           {
               //以編碼轉換方法處理資料流
               using (StreamWriter swStream = new StreamWriter(cEncrypt))
               {
                   //寫入資料流 >> mEncrypt
                   swStream.Write(plainText);
               }
               //輸出轉換成byte[]形式
               encrypted = mEncrypt.ToArray();
           }
      }
  }
  return encrypted;
}

AES解密:
要引用 using System.Security.Cryptography;

static string DecryptionByAES(byte[] cipherText, byte[] key , byte[] IV)
{
    string decrypted;

    //檢查參數
    if (cipherText == null || cipherText.Length <= 0)
        throw new ArgumentNullException("沒有要解密的內容");
    if (key == null || key.Length <= 0)
        throw new ArgumentNullException("沒有提供金鑰");
    if (IV == null || IV.Length <= 0)
        throw new ArgumentNullException("沒有提供IV");

    //這裡使用Aes創建編譯物件
    using (Aes aes = Aes.Create())
    {
        aes.Key = key;
        aes.IV = IV;

        //創建密碼解譯轉換運算
        ICryptoTransform encryptor = aes.CreateDecryptor(aes.Key, aes.IV);
        //先把密文byte放到記憶體串流,再用decrypt方法(解碼)讀取去
        using (MemoryStream mDecrypt = new MemoryStream(cipherText))
        {
            //使用CryptoStream創建解碼轉換方法
            using (CryptoStream cDecrypt = new CryptoStream(mDecrypt, encryptor, CryptoStreamMode.Read))
            {
                //以解碼轉換方法處理資料流
                using (StreamReader swStream = new StreamReader(cDecrypt))
                {
                    //讀出資料流(同時解碼)
                    decrypted = swStream.ReadToEnd();
                }
            }
        }
    }
    return decrypted;
}

AES的金鑰(KEY)和向量(IV):
  大部分使用金鑰都會使用同一把金鑰,也就是加密者和解密者必須共用一把KEY來處理,這個又稱對稱型金鑰加密(Symmetric Key Encryption),這裡也只討論這種加密方式。

  AES加解密過程必須同時使用到 KEY (秘密金鑰) IV (對稱演算法的初始化向量 (initialization vector)),一般使用的情況下,並不會特別指定使用 IV 值,因此在這個範例裡面 IV 的直是透過 KEY 以 MD5 的 Hash 產生(一般常見做法)就可以了

using(MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider())
{
    iv = md5.ComputeHash(key);
}




2017年10月15日 星期日

How customize part for Fritzing - 如何自訂 Fritzing 的元件

建議先瞭解一下 Fritzing customized part principle - Fritzing 自訂元件原則

如果不想瞭解或沒時間瞭解也沒關係,反正就是依樣畫葫蘆也可以

這裡使用的是 Fritzing 0.93b 版的,跟舊版的操作方式會有相當的出入,請注意 。

○使用的工具:

○認識 Fritzing 元件編輯器:
    這個版本的元件編輯器所在位置非常彆扭,以前它是直接列在工具『元件』裡面,現在則必須把元件拖進麵包板後才能新建元件。

1、首先開啟 Fritzing ,然後到『麵包板』

2、然後從右側『元件』拖拉一個元件到『麵包板』上,我這邊是選擇『CORE』裡面的 Mysery Part - 3 Pin

3、在『麵包板』上的元件按滑鼠右鍵叫出選單,選單裡面有個『Edit(New Parts Editor)』,點入後就可以看到元件編輯器了


元件編輯器上有6個主要標籤:
  • 麵包板(breadboard):
    主要是使用在麵包板上的圖片。
  • 概要圖(schematic):
    這邊我會稱為電路圖,因為這比較像電工科在畫的電路圖。
  • PCB:
    印刷板電路,主要是提供給製作PCB輸出時的設計使用。
  • 圖示(icon):
    顯示在元件庫上的小圖案/圖示。
  • Metadata:
    這個元件的相關資訊/訊息。
  • 連接器(Connector):
    設定這個元件的連接器/街腳/接點 編號、形式、名稱等等。
其中,前4種需要設計圖檔,但其實第4種 icon 可以使用元件編輯器直接以麵包板圖做為縮圖使用。

如果自製元件編輯完畢,記得要存檔,否則會消失不見喔!!!(它不會自動存檔)

○開始繪製圖檔:
    使用 Inkscape 繪製 SVG圖檔。
我這邊的例子是以我在網路上購買的一個旋轉編碼器為例

在SVG設計上力求尺寸標準,尤其是連接器的接腳部分,因為這會大大影響您的元件使用在麵包板上時的的孔位是否能對準。

在製作圖檔時至少要做3種圖:
麵包板用 breadboard

概要圖 schematic

PCB:


各位這邊如果使用 Inkscape 來繪製 SVG 圖檔給 Fritzing 使用時,要注意以下問題存在:
  1. 文字字型:
    Fritzing 官方網站提到,它對SVG內的文字只能支援 Droid Sans 和 OCR-A 的字型,所以也只建議設計者使用這兩種字型。不過,很糟糕的是,由 Inkscape 設計出來的圖檔內含這兩種字型,到了 Fritzing 內全部不能用,會一直提示說你的圖檔內使用了非官方建議的字型可能無法正常顯示 Bla.Bla. 的。

    所以,我的作法是,把文字轉成路徑就可以了,缺點是圖檔會變大,但也是最簡單的解決方式,而且如果你設計的圖裡面一定要用到非官方指定的文字字型,也是非得這麼做才能解決的。

    我研究過Inkscape 產生的 SVG ,發現它對字型可能使用了CSS中style的屬性設定,而 Fritzing 只能支援Tag上的inline屬性,導致無法解析,但修改SVG內容工程浩大,所以就不建議改了。

    ※Windows 內建字型並沒有這兩種字型,必須上網去自己下載來用。
    ※也許 Adobe Illustration 沒有這個問題,但我沒用過無法分析。
     
  2. 接腳的群組名稱:
    Fritzing 元件編輯器在匯入SVG圖片時會自動去對接 Pin,如果你希望 Fritzing 可以幫你處理,則你的 SVG 圖裡面的接腳(Connector) ,需要符合 Fritzing 的要求。

    就是在接腳的向量圖上(或是群組),更名成『connector數字pin』,然後再外面包上一個群組,並命名該群組為『copper數字』,如下圖:

    ※數字是從0開始。
    ※PCB的圖檔裡面至少要有一個名為 cooper0 的群組,不然 Fritzing 會不讓你匯入的。
  3. 偷機取巧方式:
    關於接腳的準確度是個頭痛的問題,沒有時間搞測量的,可以直接到 Fritzing 程式路徑下 \fritzing-parts\svg\obsolete\breadboard 裡面可以找到不少 現成的 “接腳” 可以拿來拼湊,相當方便,當然其他零件(電阻、電容等等)也可以在裡面找到不少。
○開始製作零件:
    當你把相關的圖檔準備好了以後,回到前面 Fritzing 的元件編輯器上,先開始編輯。

首先到『連接器』上編輯你的接腳,我的編碼器是5個接腳,所以要設定5,設定後
下方自動換產生5個連接器 connector0 ~ connector4,要注意的是如果你希望你的圖能夠自動貼合腳位,你在設計圖檔的接腳的順序就必須和這個地方是一致的喔!

上面腳位另外要設計的注意是『公』♂、『母』♀、『平貼』pad。
孔位是『穿孔式』Through-hole 還是『貼片式』SMD。

然後是 Metadata 元件資訊,當然資訊越完整越好。

要注意的是 Family 這個是歸屬元件庫位置,打到哪個名字就歸屬到哪個元件庫去,要注意,我這邊是打 My Parts,所以製作完後會自動歸在 My Parts 庫裡面。

另外,有個 Chip Label,如果你的概要圖 schematic 裡面有文字標籤,而且它被命名為 Label 時,這段文字會自動帶到那個文字標籤裡面。

再來開始新增圖片,首先到『麵包板』畫面,使用『檔案』→『Load image for view』,把我們做好的麵包板圖載入。



載入後,開始設計連接線(如果你的圖有按照 Fritzing 標準設計,基本上會自動對上接腳),先在右側上部選擇(點選)要設定的接腳,然後點一下 Select Graphic,然後移動滑鼠到圖面上,選擇一個區塊(它會自動標註區塊為深紫色,注意是一個接腳區塊,不是一個點喔)。


然後,將所有的接腳做過(選擇)一遍,就可以了,

接下來就是做概要圖 schematic 和 PCB,按照上面的方法載入對應的圖檔,然後選擇對接接腳



再來進入Icon 圖示,如果你沒有縮小版的圖示,也可以直接參考麵包版圖來產生即可,這裡不需要配接接腳。

當上面都做完之後,最後就是要存檔,記得要選擇另存新檔,因為我們是開原本存在的檔案來產生新的元件,所以必須另存成新元件!!

離開元件編輯器,畫面回到 Fritzing 後,你可以在 My Parts裡面看到你的新元件,但是千萬注意,雖然它顯示在畫面上了,但是該元件庫並沒有儲存(沒有自動儲存),如果這時你離開了 Fritzing ,再進入後就會發現你的辛苦會前功盡棄(元件消失了)!!!

所以一定要做最後這道手續.......儲存bin,否則到時候欲哭無淚,誰也救不了喔!

接下來恭喜你自己完成了一個新的元件的設計。

2017年10月11日 星期三

Fritzing customized part principle - Fritzing 自訂元件原則

設計 Arduino 或 Resberry pi 的人,大概都用過 Fritzing 來設計電路

雖然它是免費的(當然也接受捐款,我也捐款過),但是缺點是零件(Part)種類無法包山包海。

大家最常遇到的問題是,找不到自己正在使用的零件,所以得靠第三方(別人的)的零件庫。

雖然有第三方零件庫,但說真的,在台灣的玩家常買對岸的零件時,或特製零件(某些賣場會找工廠批量設計生產)時都會找不到零件庫可以用或是下載。

雖然,網路上也接受客製化元件庫設計,不過是要收費的,對於學生/經濟力較弱的人來說,真的都是困難,不過 Fritzing 官方網站也有教您自己如何設計元件,也歡迎您把設計元件庫放在 GitHub 上分享給別人,不過前提是你要搞懂 Fritzing 設計元件的原理和方法。

所以,我把 Fritzing 使用自訂元件的原理,和設計方法簡單的說明一下,讓有心自己設計的人可以很方便的上手。

由於原理和實作內容可能不少,所以我分成幾篇來處理:

注意我使用的 Fritzing 版本是 0.93b 的版本作業系統是 Windows ,而網路上的中文教學大部分是舊版的而且不少使用 Linux (先說聲抱歉,我沒有用過 Linux,路徑請自行轉換),所以使用上有很大落差,尤其常常會找不到對應的功能表。

關係圖

檔案位置
※沒相關資料夾的人請先安裝 Fritzing ,然後執行一次就會產生下面需要的資料夾。

Fritzing 的自訂元件通常會放在 %user%\Documents\Fritzing 下,這底下會有 Parts 和 Bins 兩個資料夾:

這個 bins 就是 Fritzing 畫面右邊那個元件庫啦~

裡面會看到 search.fzb 和 my_parts.fzb 就是對應搜尋放大鏡My Parts 元件庫(Library)的。(圖案是MINE...雖然意思是一樣,但對我們這種歪國人來說,第一時間真容易搞錯)


如果你在下拉式功能新增自己的元件庫 New Bin 然後儲存 Save Bin,就會在 bins 路徑下看到你新增的庫檔案喔~


而另一個 part 顧名思義就是放元件的設計圖的,這層有兩個主要的資料夾:user 和 svg


user 放置你的自訂元件描述檔(*.fzb),你可以把接下來的user看成是『自訂的』意思。
svg 放置圖檔(*.svg)

而進入 svg 裡面又有一個 user,再進入 user 後會看到圖檔分類資料夾: breadboard、icon、pcb、schematic

breadboard 零件外觀圖(零件貼在麵包板上使用的圖)
icon 零件概略圖(顯示在零件庫上的圖案)
pcb 設計 pcb 用的接線圖
schematic 電路圖,用來表示電路形狀的電路圖

這裡面的設計圖案,全都使用SVG向量檔案格式喔!!

建議軟體
目前 Fritzing 建議大家使用的是 Adobe Illustrator 來設計向量圖(記得要存成SVG)

當然,口袋不夠深的就用 Inkscape 了(我就是....)

什麼是fzb
    Fritzing bins 的縮寫,元件庫檔案,檔案內容是XML格式,並不複雜,內容大概是:

<?xml version="1.0" encoding="UTF-8"?>
<module fritzingVersion="0.9.3b.04.19.5c895d327c44a3114e5fcc9d8260daf0cbb52806" icon="Mine.png">
    <title>My Parts</title>
    <instances>
        <instance moduleIdRef="Keyes_Rotary_Decoder_Switch_5812070981c131c2523c4b742f878507_12" modelIndex="5868" path="C:/Users/user/Documents/Fritzing/parts/user/Keyes_Rotary_Decoder_Switch_5812070981c131c2523c4b742f878507_12.fzp">
            <views/>
        </instance>
        <instance moduleIdRef="LCD 2004A 20x4 IIC_189cbb099f50a650d8ed5245f2d61f6d_8" modelIndex="5913" path="C:/Users/user/Documents/Fritzing/parts/user/LCD 2004A 20x4 IIC_189cbb099f50a650d8ed5245f2d61f6d_8.fzp">
            <views/>
        </instance>
        <instance moduleIdRef="MH-Real-Time-Clock-Module-2_DS1302_842a2ca78fa9e77c46110042b1521fc8_7" modelIndex="85411603" path="C:/Users/user/Documents/Fritzing/parts/user/MH-Real-Time-Clock-Module-2_DS1302_842a2ca78fa9e77c46110042b1521fc8_7.fzp">
            <views/>
        </instance>
    </instances>
</module>


注意看可以看出個端倪,就是描述這個元件庫的名稱<title>與這個庫裡面有哪些元件<instances>,每個元件<instance>裡面又描述編號moduleIdRef、索引modelIndex、元件描述檔路徑path。


什麼是fzp
    Fritzing parts 的縮寫,元件描述檔案,內容也是XML格式,大概的樣式如下

<?xml version='1.0' encoding='UTF-8'?>
<module referenceFile="mystery_part_sip_3_100mil.fzp" moduleId="Keyes_Rotary_Decoder_Switch_5812070981c131c2523c4b742f878507_12">
 <version>4</version>
 <author>wildox</author>
 <title>Rotary Decoder with switch</title>
 <label>Rotary Decoder with switch</label>
 <date>週日 十月 8 2017</date>
 <tags>
  <tag>mystery part</tag>
  <tag>fritzing core</tag>
 </tags>
 <properties>
  <property name="variant">v1</property>
  <property name="family">My parts</property>
  <property name="pin spacing">100mil</property>
  <property name="hole size"></property>
  <property name="pins">5</property>
  <property name="layout">Single Row</property>
  <property name="layer"></property>
  <property name="chip label">keyes</property>
  <property name="package">THT</property>
  <property name="part number"></property>
  <property name="editable pin labels">false</property>
 </properties>
 <taxonomy>part.mystery.magical.3.pins</taxonomy>
 <description>&lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
&lt;html>&lt;head>&lt;meta name="qrichtext" content="1" />&lt;style type="text/css">
p, li { white-space: pre-wrap; }
&lt;/style>&lt;/head>&lt;body style=" font-family:'PMingLiU'; font-size:9pt; font-weight:400; font-style:normal;">
&lt;p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">This Rotary decoder using pullup resistor and with a switch at push down button&lt;/p>&lt;/body>&lt;/html></description>
 <views>
  <iconView>
   <layers image="icon/Keyes_Rotary_Decoder_Switch_842a2ca78fa9e77c46110042b1521fc8_1_icon.svg">
    <layer layerId="icon"/>
   </layers>
  </iconView>
  <breadboardView>
   <layers image="breadboard/Keyes_Rotary_Decoder_Switch_842a2ca78fa9e77c46110042b1521fc8_1_breadboard.svg">
    <layer layerId="breadboard"/>
   </layers>
  </breadboardView>
  <schematicView>
   <layers image="schematic/Keyes_Rotary_Decoder_Switch_842a2ca78fa9e77c46110042b1521fc8_1_schematic.svg">
    <layer layerId="schematic"/>
   </layers>
  </schematicView>
  <pcbView>
   <layers image="pcb/Keyes_Rotary_Decoder_Switch_842a2ca78fa9e77c46110042b1521fc8_1_pcb.svg">
    <layer layerId="silkscreen"/>
    <layer layerId="copper0"/>
    <layer layerId="copper1"/>
   </layers>
  </pcbView>
 </views>
 <connectors>
  <connector name="CLK" type="male" id="connector0">
   <description>Clock</description>
   <views>
    <breadboardView>
     <p terminalId="connector0terminal" layer="breadboard" svgId="connector0pin"/>
    </breadboardView>
    <schematicView>
     <p terminalId="connector0terminal" layer="schematic" svgId="connector0pin"/>
    </schematicView>
    <pcbView>
     <p layer="copper0" svgId="connector0pin"/>
     <p layer="copper1" svgId="connector0pin"/>
    </pcbView>
   </views>
  </connector>
  <connector name="DAT" type="male" id="connector1">
   <description>Data</description>
   <views>
    <breadboardView>
     <p terminalId="connector1terminal" layer="breadboard" svgId="connector1pin"/>
    </breadboardView>
    <schematicView>
     <p terminalId="connector1terminal" layer="schematic" svgId="connector1pin"/>
    </schematicView>
    <pcbView>
     <p layer="copper0" svgId="connector1pin"/>
     <p layer="copper1" svgId="connector1pin"/>
    </pcbView>
   </views>
  </connector>
  <connector name="SW" type="male" id="connector2">
   <description>switch</description>
   <views>
    <breadboardView>
     <p terminalId="connector2terminal" layer="breadboard" svgId="connector2pin"/>
    </breadboardView>
    <schematicView>
     <p terminalId="connector2terminal" layer="schematic" svgId="connector2pin"/>
    </schematicView>
    <pcbView>
     <p layer="copper0" svgId="connector2pin"/>
     <p layer="copper1" svgId="connector2pin"/>
    </pcbView>
   </views>
  </connector>
  <connector name="+" type="male" id="connector4">
   <description>Vcc</description>
   <views>
    <breadboardView>
     <p layer="breadboard" svgId="connector4pin"/>
    </breadboardView>
    <schematicView>
     <p layer="schematic" svgId="connector4pin"/>
    </schematicView>
    <pcbView>
     <p layer="copper0" svgId="connector4pin"/>
     <p layer="copper1" svgId="connector4pin"/>
    </pcbView>
   </views>
  </connector>
  <connector name="GND" type="male" id="connector5">
   <description>GND</description>
   <views>
    <breadboardView>
     <p layer="breadboard" svgId="connector5pin"/>
    </breadboardView>
    <schematicView>
     <p layer="schematic" svgId="connector5pin"/>
    </schematicView>
    <pcbView>
     <p layer="copper0" svgId="connector5pin"/>
     <p layer="copper1" svgId="connector5pin"/>
    </pcbView>
   </views>
  </connector>
 </connectors>
</module>


這個內容比較複雜,簡單說幾個地方:
<properties>放置這個元件的主要特性描述
<iconView>底下 layers image 放置 icon 圖檔的檔案位置
<breadboardView>底下 layers image 放置 breadboard 圖檔的檔案位置
<schematicView>底下 layers image 放置 schematic 圖檔的檔案位置
<pcbView>底下 layers image 放置 pcb 圖檔的檔案位置

※注意上面的檔案路徑是相對路徑,而fzb是絕對路徑

另外<connectors>這一大段是在描述每個連接點<connector>在 breadboard、schematic、pcb 這些圖上面的位置,而這些位置一般都是對應到SVG檔案裏面的某個元素ID,所以當你在設計SVG的時候,有正確使用 Fritzing 官方網站的建議設計方式,可以在你設計新元件時載入圖片後,編輯器就會自動對應上該圖片上的連接點喔。




2017年9月30日 星期六

在Windows 7上架設自己的 DNS 服務(使用BIND 9)


這是因應自己需要架設 DNS 伺服器紀錄的
在沒有Windows Server和Linux作業環境中,利用PC版的Windows開設DNS服務的方式

BIND的官方網站: https://www.isc.org
BIND下載位置(如果不存在請到官方網站尋找):https://www.isc.org/downloads/

找到下面位置,然後點開BIND項目產生下拉選單,選擇下載版本點選Download,依照作業系統類型選擇下載。
我下載的版本是9.10.6穩定版,作業系統是64位元



下載後是一個壓縮檔,把它解壓縮,會看到一個安裝檔案 BINDinstall.exe
注意,你必須以系統管理員身份執行,否則安裝後會有很多問題



雙擊後進行安裝,下面如下:
     注意中間紅框,這個是 BIND啟動用的帳號 [named],一般而言電腦不會有這個帳號,所以它會在安裝時幫你建立這個帳號,當然這個建立過程是有問題的,所以我們事後要去調整這個帳號的權限。


還有一些需要注意(檢查)的:

  1. 安裝完畢後,程式正常的安裝位置會在 C:\Program Files\ISC BIND 9,如果你的路徑跑到 C:\Program Files (x86)\ISC BIND 9,代表你的作業系統是64位元,而你下載到的BIND版本是 32位元的。
     
  2. 某些版本BIND的組態設定檔會在 C:\Windows\System32\dns\etc,但是這個版本的組態預設是在 C:\Program Files\ISC BIND 9\etc,而程式與工具路徑會放在 C:\Program Files\ISC BIND 9\bin,要注意的是 C:\Program Files\ISC BIND 9\etc 基本上是空的,接下來所有組態檔都必須自己建立,這點對新手真的不是很友善。
     
  3. 某些套裝電腦會把作業系統的administrator帳號鎖起來,讓使用者以別的帳號執行,雖然這個使用者帳號是可能編屬於administrators權組的,但是對於C:\Program Files和C:\Windows的權限還是有一些限制的,對於接下來要建立BIND的組態與設定會有很多不便(通常是無法儲存設定檔到C:\Program Files\ISC BIND 9\etc)。

    所以建議執行BIND任何設定或是開啟編輯器編輯組態檔案前,記得使用右鍵『以系統管理員身份執行』,或是直接使用administrators帳號登入進行編輯。

修改[named]帳號權限(成員隸屬):
     原則上是不需要修改的,除非你的日誌(寫入)路徑是放在 C:\Program Files\ISC BIND 9\etc 底下,或是你的BIND需要抄寫其他DNS清單(會修改C:\Program Files\ISC BIND 9\etc裡面檔案)就會需要把權限調高。



組態檔案:
      先了解BIND9需要自行建立底下一些檔案:

  • rndc.key
  • name.conf
  • named.root
  • named.local
  • localhost.zone
  • mysite1.com.tw.dns
  • mysite2.idv.tw.dns


除了rndc.key、named.conf 之外,其他檔案名稱其實可以自己訂沒有硬性規定,但基於日久怕忘,所以我是以常見公版的命名方式處理。

檔尾名稱.dns的檔案是我的網域裡面主機名稱 正解 清單(玩過windows server的DNS的人大概就瞭解)

在這裡我沒有設定反解清單,大部分的情況下,只有公司內部比較有機會使用反解,一般架設在外部的主機通常是租用或是資安的理由不會設定。




  • rndc.key
    加密序號檔案,由系統指令產生。
     
  • name.conf
    主要組態檔案。
     
  • named.root
    根(root)主機清單,可以到 ftp://rs.internic.net/domain 直接下載最新的 named.root,不定期更新(基本上很少會異動)。
     
  • named.local
    本機形式 正解 清單
     
  • localhost.zone
    本機形式 反解 清單
     
  • mysite1.com.tw.dns
    我的第一個網站 正解 清單,.dns前面的檔案名稱通常會以你申請的域名為主(當然也可以完全不相關,只是這樣比較好記)。
     
  • mysite2.idv.tw.dns
    我的第二個網站 正解 清單
     

設定方式/步驟:

  1. 檢視C:\Program Files\ISC BIND 9\bin\readme1st.txt,內容主要是說,請先建立一個 named.conf 純文字檔案,儲存位置在 C:\Program Files\ISC BIND 9\etc ,然後先建立一個內容然後儲存:
    options {
            directory "C:\Program Files\ISC BIND 9\etc";
    };
     
  2. 產生 rndc.key ,開啟命令列模式,進入 C:\Program Files\ISC BIND 9\bin,執行
    rndc-confgen -a
    便會自動產生這個檔案,而預設產生路徑就在 C:\Program Files\ISC BIND 9\etc 。
     
  3. 然後把rndc.key內容複製到 named.conf  內:
    key "rndc-key" {
            algorithm hmac-md5;
            secret "lJNu1IPdgmnej+ZzGYAbVA==";
    };
    注意 secret "lJNu1IPdgmnej+ZzGYAbVA==";  這序號每次產生都會不一樣。

    ,然後再加上 controls 文字:
    controls {
            inet 127.0.0.1 port 953 allow { localhost; } keys { "rndc-key"; };
    };
     
  4. 依照需要繼續加上 named.conf 設定項目:
    • options : 操作設定說明(不想看直接跳範例)
      • directory "設定檔操作路徑"
        告訴 BIND 設定檔的位置
      • version "自訂的版本訊息"
      • zone-statistics yes | no ;
        是否開啟 ZONE 狀態記錄
      • statistics-file "檔案位置"
        配合 zone-statistics yes; 告訴 BIND 儲存 ZONE 狀態的檔案位置
      • allow-query { IP條件 };
        允許來查詢的IP/網段/單機
      • allow-recursion { IP條件 } ;
        允許來遞迴查詢的IP/網段/單機
      • allow-transfer { IP條件 };
        允許來讀取本機清單的IP/網段/單機
      • recursion yes | no ;
        遞迴查詢全開/全關,這個和 allow-recursion 只使用其中一種設定
      • transfer yes | no ;
        讀取本機清單 全開/全關,這個和 allow-transfer 只使用其中一種設定
      • forwarders { 其他 DNS IP };
        當本機查無資訊時,將查詢條件送往其他 DNS 主機查詢
        例如:forwarders { 168.95.1.1; 8.8.8.8; }; 意思是當本DNS查無資料時送往中華電信DNS或Google的DNS進行查詢,此種查詢稱為遞迴查詢,可以配合 recursion 設定來限制特定使用者使用,以免被人利用。
    • zone : 轄區(網域)宣告設定說明
      • 語法和指令
        • zone "正反解轄區名稱" IN {}; : 架構樣式
        • type master|slave|stub|forward|hint : 類型
        • file "紀錄檔案" :實際內容檔案
        • allow-update {IP;|範圍;|none;} :允許更新內容(此處為轄區獨立設定,如若 options 有定義則會以 options 為主)
        • allow-transfer {IP;|範圍;|none;} :允許轉送內容
        • 其他指令眾多有興趣可以Google研究
      • 根目錄資訊(必要) zone "." {
                type hint;
                file "named.root";
        };
      • 本機正解清單資訊 zone "localhost" IN {
                type master;
                file "localhost.zone";
                allow-update {none;};
        };
      • 本機反解清單資訊 zone "0.0.127.in-addr.arpa" {
                type master;
                file "named.local";
                allow-update {none;};
        };
      • 自訂網域正解清單資訊(至少一個,我的範例是二
        個網站) zone "mysite1.com.tw" {
                type master;
                file "mysite1.com.tw.dns"; //第一網站
                allow-update {none;};
        };

        zone "mysite2.idv.tw" {
                type master;
                file "mysite2.idv.tw.dns"; //第二網站
                allow-update {none;};
        };
    • logging : 日誌產生設定說明
      • 語法和指令 logging {
                channel 種類-log{
                        file "儲存檔案名稱" versions 保留檔案數 size 每個檔案大小;
                        severity critical|error|warning|notice|info|debug|dynamic; 要紀錄的告警等級
                        print-time yes|no; 列印時間
                        print-severity yes|no; 列印告警等級名
                        print-category yes|no; 列印類別名
                };
                category client|config|database|default|delegation-only|dispatch|dnssec|general|lame-servers|network|notify|queries|resolver|rpz|rate-limit|security|unmatched|update|update-security|xfer-in|xfer-out; 要輸出的類別
        };
      • 用法 logging{
                channel default-log {
                        file "D:\ISC_BIND_log\named_default.log" versions 5 size 200m;
                        severity info;
                        print-time yes;
                };
                category default { default-log; };
        };
    • 其他
      在 named.conf 裡面 options 和 logging 段落只會有一個,zone 則可以有好幾個。
    • 範例 options {
          directory "C:\Program Files\ISC BIND 9\etc";
          zone-statistics yes;
          statistics-file "C:\Program Files\ISC BIND 9\etc\data\named_stats.txt";
          version "none of your business";
          //限制遞迴查詢
          allow-recursion {192.0.0.0/8; 127.0.0.1/32;};
          //限制轉送清單
          allow-transfer {192.168.2.0/24; };
          forwarders {
              168.95.1.1;
              139.175.10.20;
              8.8.8.8;
          };
      };
      key "rndc-key" {
          algorithm hmac-md5;
          secret "lJNu1IKdgmnej+ZzUYAbVA==";
      };
      controls {
          inet 127.0.0.1 port 953 allow { localhost; } keys { "rndc-key"; };
      };
      zone "." {
          type hint;
          file "named.root";
      };
      zone "localhost" IN {
          type master;
          file "localhost.zone";
          allow-update {none;};
      };
      zone "0.0.127.in-addr.arpa" {
          type master;
          file "named.local";
          allow-update {none;};
      };

      zone "mysite1.com.tw" {
          type master;
          file "mysite1.com.tw.dns";
          allow-update {none;};
      };
      zone "mysite2.idv.tw" {
          type master;
          file "mysite2.idv.tw.dns";
          allow-update {none;};
      };
      logging{
          channel default-log {
              file "D:\ISC_BIND_log\named_default.log" versions 5 size 200m;
              severity info;
              print-time yes;
          };
          channel security-log {
              file "D:\ISC_BIND_log\named_security.log" versions 3 size 100m;
              severity info;
              print-severity yes;
              print-time yes;
              print-category yes;
          };
          channel query-log {
              file "D:\ISC_BIND_log\named_query.log" versions 10 size 200m;
              severity info;
              print-time yes;
          };
          channel lamer-log {
              file "D:\ISC_BIND_log\named_lamer.log" versions 3 size 100m;
              severity info;
              print-severity yes;
              print-time yes;
              print-category yes;
          };
          category default { default-log; };
          category security { security-log; };
          category queries { query-log; };
          category lame-servers { lamer-log; };
      };

     
  5. 建立named.root(zone file)
    這個就直接從 ftp://rs.internic.net/domain 直接下載最新的 named.root 就好。
     
  6. 建立localhost.zone(zone file)正解資訊檔
    ※藍色字在實際使用時要拿掉以免有問題
    $TTL 86400    (資訊有效期)
    $ORIGIN localhost.    (宣告全區域屬性)
    @ 1d IN SOA @ root (
            42;      Serial (序號:Slave判斷是否需更新檔案)
            3H;     Resresh (Slave自動來取得檔案的時間)
            15M;  Retry (若refresh失敗,再度取得檔案的時間)
            1W;    Expire (若refresh失敗,保留該網域的時間)
            1D) ;   Minimum TTL 別台DNS 伺服器保留cache的時間)
        1D IN NS @
        1D IN A 127.0.0.1

    1D IN NS @  為第一筆NS記錄指出本地網域名稱為localhost.
    1D IN A 127.0.0.1 指出第一筆A記錄對應為本機網用名稱伺服器IP 127.0.0.1
  7. 建立named.local(zone file)反解資訊檔
    $TTL 86400
    @ IN SOA localhost. root.localhost. (
            2017 ;      Serial
            28800 ;      Resresh
            14400 ;      Retry
            3600000 ;      Expire
            86400 ) ;      Minimum TTL
        IN NS localhost.
    1 IN PTR localhost.

    那個紅色1是本機(DNS)的IP最後一碼(本機IP是 127.0.0.1)
     
  8. 建立主機清單(zone file) mysite1.com.tw.dns 和 mysite2.idv.tw.dns檔案
    這裡只做一個範例 mysite1.com.tw.dns

    $TTL 86400
    @ IN SOA dns.mysite1.com.tw. hostmaster.mysite1.com.tw. (
            001 ;Serial
            10800 ;Resresh
            600 ;Retry
            86400 ;Expire
            3600 ) ;Minimum TTL
        IN NS dns.mysite1.com.tw.
        IN MX 10 sp4.mail.com.
        IN MX 20 sp3.mail.com.
        IN MX 30 spam.mysite1.com.tw.

    webmail IN CNAME mail.mysite1.com.tw.
    dns IN A 61.233.159.103
    ftp IN A 61.233.159.102
    mail IN A 61.233.159.99
    service IN A 61.233.159.102
    spam IN A 61.233.159.89
    sydb IN A 61.233.159.101
    webserv1 IN A 61.233.159.110
    www IN A 61.233.159.76


     
  9. 清單檔案注意事項:
    每個檔案結尾必須是 NewLine (換行) 字元符號。
    每個條件後面必須以 ; (分號) 作為結束。
啟動 BIND:
    請到 『控制台』→『系統管理工具』→『服務』裡面找到『ISC BIND』,這個項目預設是沒有啟動的,然後啟動它

    如果無法啟動,請到『事件檢視器』→『Windows紀錄』→『應用程式』查看來源是『named』,通常第一個錯誤是主要的訊息來源。

    錯誤員因常見像是:

    檔案找不到
zone 0.0.127.in-addr.arpa/IN: loading from master file named.local failed: file not found
    紀錄重覆
dns_master_load: mysite1.com.tw.dns:33: webmail.mysite1.com.tw: multiple RRs of singleton type
    註解放錯位置
dns_rdata_fromtext: named.local:9: near '//本機的IP': extra input text
    打錯關鍵字
C:\Program Files\ISC BIND 9\etc\named.conf:78: unknown option '3'
    結尾漏掉分號
C:\Program Files\ISC BIND 9\etc\named.conf:73: missing ';' before '10'
    檔案結尾不是換行(NewLine)字元
localhost.zone: file does not end with newline

    修正問題後,重新啟動,只要沒有重大錯誤,一般而言都可以運作的。

這時候就要恭喜你,完成DNS伺服器的架設了。


參考文章: