SIKULI 為 GUI 自動化開了一道門
01/28/2010, 13:21 - Open Source
前天試用了一下來自台灣台中的 vgod 在MIT修業兩年的成果, SIKULI Project, 發覺這真的是像 vgod 自己在 Blog 說的是會改變 GUI 世界的東西啊. 這是可以將 GUI 的原本需要人一個一個click的用法, 變成 batch 的方式. 也就是說可以將多個 GUI 程式經由 SIKULI 串在一起, 完成一件事, 或者是可以將原本需要人用Mouse在電腦之前,一步一步的確認及回應, 現在可以將這些動作自動化了. 可以自動化對於常用電腦執行固定工作項目的人,是很重要的一個需求.讓電腦將經常需要重覆的工作自動化, 這樣人才有時間作別的事, Work Smart, do'nt work hard, 意思是說要聰明的工作, 而不要白費力氣的工作啊. 有了自動的 GUI script 正好補完了多年來 GUI 無法自動化的缺口.在Macintosh 有 Apple script可以作類似的工作, 不過前提是 GUI 程式要有支援 Scriptable 的介面, 和 Apple Script 連結起來, 才可以用 script 控制 GUI 的程式工作. 而在 UNIX 系統上(Linux/BSD/Solaris/AIX...都是), 可以用的 script 就更多了, Shell script, Perl, PHP, Python, Ruby, TCL/Tk, Expect等等, 各有不同的語法及用途, 不過有一個共通點, 就是只能用在文字模式, 或是自己所構成的 GUI 環境, 無法和別的 GUI 程式互動. 在 Microsoft 的作業系統上的 script 就更弱了, 來自80年代的 DOS batch file, 以少得可憐的指令, 及奇怪的用法, 一樣是工作文字模式下, 可以經由 VBScript 作出 GUI 及使用 OLE 和別的程式作有限度的互動, 雖然有人作出了 Autoit 和 AutoHotkey, 不過都需要使用文字程式碼寫成 script, 而這都需要一定的程式語言使用背景才可以完成,還是沒有 SIKULI 直接及簡單. 以前有一個作業系統叫 BeOS,可以用Cortex 在 GUI 中將各不同的影音來源輸入和輸出串在一起,一起工作,例如從介面錄音之後直接送到MP3 encoder壓縮後,再送到音效卡輸出,全部用GUI將線接在一起就可以,不過 BeOS 已經是昨日黃花,已經進入歷史了,現在有的只有一個相容的 Open source 計畫,叫作 Haiku。
SIKULI 使用的方法說起來也很簡單, 就是先將要做動作的圖象, 用 screen capture 給剪下來, 在執行 script 時進行比對, 若有一定程度的相似性(可在 script 中設定),就作 script 中指定的動作, 如 type 一段文數字,或是按一下 botton. 這樣子的作法是比較慢, 但好處是沒有作業系統相容的問題, 也沒有需要連結程式庫或預先作好的介面問題, 一切都和人在使用 GUI 介面時一樣, 用眼睛看, 選擇相對 icon, 作出對應的事件,像是按一次,或兩次, 或輸入資料等. 夠直接了吧!
我花了三分鐘就作了一個可以將 Windows 關機的 script.

簡單吧,在 SIKULI 的網頁上還有很多的例子。
最棒的是 SIKULI 是 Open source, 所以應該可以在任何電腦系統上,經過一定的修補後執行. SIKULI 使用 Jython, 所以要有 Java JDK/JRE 才可以執行.不過在 Windows 版的好像 save 就會 crash, 而 OS X 版的就不會. Linux 還在和 OpenCV Library 打架中. 在 Windows 版本上可以設定 screen capture 的時間 delay, 以免還沒有找到要按的按鍵就 timeout 了. 我是設成 3 秒, 好像比較可以符合慢慢的 Windows XP.
SIKULI 使用 Jython, 所以要有 Java JDK/JRE 才可以執行. 在作 screenshut 時要注意的是背景顏色, 會干擾圖象辦認的正確, 在使用時要小心. 也可以先用別的程式將圖象抓下來, 再放到 script 中, 可以節省時間. 我看到的是 SIKULI 使用 png 格式, 不知道 jpeg 和 gif 可不可以. 因為 SIKULI 現在還在 beta 版, 所以文件部份只有簡單的說明1, 希望未來會有較多較詳細的說明.
不過因為 SIKULI 是使用圖象辦認,所以看來 script 的可移動性會低一點,因為各作業系統,或每個人使用的圖象都可以自行改變,而改了當然就無法正確辦認出來了。
現在 vgod 用 SIKULI 為大家開了一扇門, 接下來要如何使用就看我們了吧! 像是測試軟體的可用性, 操作測試儀器, 或是經由多個程式共同完成一個工作等等. 去拿來試試吧, 並把你認為可以加強或不足的部份告訴 vgod , 或者自己從 source code 修改成你要的樣子.
SIKULI 網址 http://sikuli.org
vgod Blog http://blog.vgod.tw
vgod 在 twitter 上開了一個 SIKULI 的專推 sikuli@twitter
Arduino WebSwitch
12/14/2009, 17:13 - Open Source
加入了將設定寫至 Flash memory 及將 string 用 PANGMEM 放至 Flash memory 以縮小 RAM 的用量。因為測試用的 Arduino 只有 1024 byte RAM,所以要用時間換取空間,不然 1024 byte 很快就用光了。而且將原本一個 function 到底的程式,區分為多個共用 functions 以節省 Flash memory 的用量。看來效果還不錯,不過程式的可讀性變得很低。下一個來試試 Telnet 和 Finger,若拿到 ATMega328 就有 2K RAM 和 32K Flash memory 可以用,就可以將所有的 services 放在一起了。 這個程式很簡單,在 8 支 digital pin 上,連接電晶體當電子開關,控制 Relay 或 SSR,作為網路可控制110V/220V的 8 孔電源開關。可以由 Web browser 得知開關的狀態。預設的 IP address 是用 169.254.0.0/16 所以可以在一開始時用簡單 Crossover 線,接上PC Windows (設定為 DHCP)的方式設定好正確的 IP,也可以設定開關的 default 狀態。
/*
This program is wor Arduino Ethernet Shield with W5100 ethernet chip,
As a 8 digital pins control in web page
Version : 1.0
Programmer : Tasuka Hsu, Dec 1 2009
*/
// Library import
#include <Ethernet2.h>
#include <Print.h>
#include <Server.h>
#include <Client.h>
#include <EEPROM.h>
#include <avr/pgmspace.h>
// Const define
#define LENGTH 50 // Message length
#define PINS 8 // Digital pins 1 to 8
#define EEPROM_START_ADDRESS 0
#define EEPROM_MAC EEPROM_START_ADDRESS+10
#define EEPROM_IP EEPROM_MAC+6
#define EEPROM_SUBNET EEPROM_IP+4
#define EEPROM_GATEWAY EEPROM_SUBNET+4
#define EEPROM_PORT EEPROM_GATEWAY+4
#define EEPROM_REFRESH EEPROM_PORT+2
#define EEPROM_SW EEPROM_REFRESH+2
#define EEPROM_RESERVED EEPROM_SW+8
// MAC Address
byte MAC[]={0x80,0x0c,0x01,0x01,0xef,0xfe};
byte Default IP Address setting
byte IP[]={169,254,1,1};
byte GATEWAY[]={0,0,0,0};
byte SUBNET[]={255,255,0,0};
//byte IP[]={172,16,7,250};
//byte GATEWAY[]={172,16,7,254};
//byte SUBNET[]={255,255,255,248};
byte SW[PINS]={0,0,0,0,0,0,0,0}; /* Switch defult state config */
unsigned int PORT=80; // HTTP port
unsigned int REFRESH=120; // HTTP refresh timer
// Keep Strings in Flash Memory not load into RAM for RAM space save
static char TITLE_S[] PROGMEM = "Adruino Digital Pins Control";
static char ANNOUNCE[] PROGMEM = "Tasuka Lab";
static char FOOTER0[] PROGMEM = "Open source of hardware and software for Arduino";
static char FOOTER1[] PROGMEM = "Program By Tasuka Hsu";
static char ARDUINO_WEB[] PROGMEM = "http://www.arduino.cc";
static char HTML_HEADER0[] PROGMEM = "HTTP/1.1 200 OK";
static char HTML_HEADER1[] PROGMEM = "Content-Type: text/html; charset=utf-8";
static char HTML[] PROGMEM = "<html>";
static char HTML_[] PROGMEM = "</html>";
static char TITLE[] PROGMEM = "<title>";
static char TITLE_[] PROGMEM = "</title>";
static char HEAD[] PROGMEM = "<head>";
static char HEAD_[] PROGMEM = "</head>";
static char CENTER[] PROGMEM = "<center>";
static char CENTER_[] PROGMEM = "</center>";
static char BODY[] PROGMEM = "<body>";
static char BODY_[] PROGMEM = "</body>";
static char INPUT_TEXT[] PROGMEM = "<input type=\"text\" name=\"";
static char INPUT_TEXT_[] PROGMEM = "\" value=\"";
static char INPUT_TEXT__[] PROGMEM = "\" size=\"";
static char INPUT_TEXT___[] PROGMEM = "\">";
static char INPUT_RADIO[] PROGMEM = "<input type=\"radio\" name=\"";
static char META[] PROGMEM = "<meta http-equiv=\"refresh\" content=\"";
static char META_[] PROGMEM = ";url=/\">";
static char SUBMIT[] PROGMEM = "<input type=\"submit\" value=\"Send\">";
static char CLEAR_BUF_CHKBX[] PROGMEM = "Clear Config<input type=\"checkbox\" name=\"cl0\">";
static char CHKBOX[] PROGMEM = "<input type=\"radio\" name=\"";
static char URL_BTN_RETURN[] PROGMEM ="<a href=\"/\"><input type=\"button\" value=\"Return\"></a>";
static char URL_BTN_BACK[] PROGMEM = "<a href=\"/?g=1\"><input type=\"button\" value=\"Back\"></a>";
static char URL_BTN_CONFIG[] PROGMEM ="<a href=\"/?g=1\"><input type=\"button\" value=\"Config\"></a>";
static char FORM[] PROGMEM = "<form method=\"GET\" action=\"/\">";
static char FORM_[] PROGMEM = "</form>";
static char DIGITAL_TITLE[] PROGMEM = "<tr><td>Digital Pin</td><td>On</td><td>Off</td></tr>";
static char TABLE_BORDER[] PROGMEM = "<table border=\"1\" align=\"center\">";
static char TABLE_NO_BORDER[] PROGMEM="<table border=\"0\" align=\"center\">";
static char TABLE_[] PROGMEM = "</table>";
static char MAC_CONFIG[] PROGMEM = "<a href=\"/?g=2\">Config MAC Address</a>";
static char IP_CONFIG[] PROGMEM = "<a href=\"/?g=3\">Config IP Address</a>";
static char SUBNET_CONFIG[] PROGMEM = "<a href=\"/?g=4\">Config Subnet Mask</a>";
static char GATEWAY_CONFIG[] PROGMEM ="<a href=\"/?g=5\">Config Gateway Address</a>";
static char PORT_CONFIG[] PROGMEM = "<a href=\"/?g=6\">Config TCP Port</a>";
static char REFRESH_CONFIG[] PROGMEM ="<a href=\"/?g=7\">Config HTML Refresh Time</a>";
static char SW_CONFIG[] PROGMEM = "<a href=\"/?g=8\">Config SW Default State</a>";
static char MAC_TITLE[] PROGMEM = "<tr><td>MAC Address</td><td>";
static char IP_TITLE[] PROGMEM = "<tr><td>IP Address</td><td>";
static char SUBNET_TITLE[] PROGMEM = "<tr><td>Subnet Mask</td><td>";
static char GATEWAY_TITLE[] PROGMEM = "<tr><td>Gateway</td><td>";
static char PORT_TITLE[] PROGMEM = "<tr><td>TCP Port</td><td>";
static char REFRESH_TITLE[] PROGMEM = "<tr><td>HTML Refresh Time</td><td>";
static char SW_TITLE[] PROGMEM = "<tr><td>Switch Default State</td><td>";
static char TD_TR_[] PROGMEM = "</td></tr>";
static char TD_TR_BR[] PROGMEM = "</td></tr><br><tr><td>";
static char ON_OFF[] PROGMEM = "<tr><td></td><td>On/Off</td></tr>";
static char CHECKED[] PROGMEM = "\" checked=\"checked";
static char SPACE[] PROGMEM = " ";
// The string address pointer
PROGMEM const char *string_table[]={
TITLE_S, //0
ANNOUNCE,
FOOTER0,
FOOTER1,
ARDUINO_WEB,
HTML_HEADER0, //5
HTML_HEADER1,
HTML,
HTML_,
TITLE,
TITLE_, //10
HEAD,
HEAD_,
CENTER,
CENTER_,
META, //15
BODY,
BODY_,
INPUT_TEXT,
INPUT_TEXT_,
INPUT_TEXT__, //20
INPUT_TEXT___,
SUBMIT,
CLEAR_BUF_CHKBX,
URL_BTN_RETURN,
URL_BTN_BACK, //25
URL_BTN_CONFIG,
TABLE_,
FORM,
META_,
DIGITAL_TITLE, //30
TABLE_BORDER,
MAC_CONFIG,
IP_CONFIG,
SUBNET_CONFIG,
GATEWAY_CONFIG, // 35
PORT_CONFIG,
REFRESH_CONFIG,
TABLE_NO_BORDER,
MAC_TITLE,
IP_TITLE, //40
SUBNET_TITLE,
GATEWAY_TITLE,
PORT_TITLE,
REFRESH_TITLE,
INPUT_RADIO, //45
FORM_,
TD_TR_,
SW_CONFIG,
SW_TITLE,
CHKBOX, //50
TD_TR_BR,
ON_OFF,
CHECKED,
SPACE
};
// RAM buffer for strings move from flash memory
char buffer[70];
// CGI GET messages buffer
char MESSAGE[LENGTH+1];
byte page=0;
boolean bootUp=true;
// HTTP Server setting
//Server server=Server(PORT);
// Load string's content from Flash memory by index of pointer to RAM
void get2RAM(byte k)
{
strcpy_P(buffer,(char *)pgm_read_word(&(string_table[k])));
}
void ReadWriteConfig()
{
byte i=0;
get2RAM(1);
// Write default data to EEPROM
if((EEPROM.read(EEPROM_START_ADDRESS)!=buffer[0])&&(EEPROM.read(EEPROM_START_ADDRESS+1)!=buffer[1])){
for(i=0;i<10;i++){
EEPROM.write(EEPROM_START_ADDRESS+i,buffer);
if(i<PINS){
EEPROM.write(EEPROM_SW+i,LOW);
SW=0;
if(i<6){
EEPROM.write(EEPROM_MAC+i,MAC);
if(i<4){
EEPROM.write(EEPROM_IP+i,IP);
EEPROM.write(EEPROM_GATEWAY+i,GATEWAY);
EEPROM.write(EEPROM_SUBNET+i,SUBNET);
}
}
}
}
EEPROM.write(EEPROM_PORT,byte((PORT&0xff00)/256));
EEPROM.write(EEPROM_PORT+1,byte(PORT&0x00ff));
EEPROM.write(EEPROM_REFRESH,byte((REFRESH&0xff00)/256));
EEPROM.write(EEPROM_REFRESH+1,byte(REFRESH&0x00ff));
}else{
// Read config data from EEPROM
for(i=0;i<PINS;i++){
SW=EEPROM.read(EEPROM_SW+i);
if(i<6){
MAC=EEPROM.read(EEPROM_MAC+i);
if(i<4){
IP=EEPROM.read(EEPROM_IP+i);
GATEWAY=EEPROM.read(EEPROM_GATEWAY+i);
SUBNET=EEPROM.read(EEPROM_SUBNET+i);
}
}
}
PORT=(int(EEPROM.read(EEPROM_PORT))*256)+int(EEPROM.read(EEPROM_PORT+1));
REFRESH=(int(EEPROM.read(EEPROM_REFRESH))*256)+int(EEPROM.read(EEPROM_REFRESH+1));
}
}
void char2Hex(byte m)
{
byte j=0;
for(byte i=0;i<2;i++){
if(i==0){
j=(m&0xf0)/16;
}else{
j=m&0x0f;
}
if(j>=0&&j<=9){
buffer=char(int(j)+'0');
}else{
buffer=char(int(j)+'A'-10);
}
}
buffer[2]='\0';
}
byte getIP(byte i,byte t)
{
byte j=MESSAGE[i+2]-'0';
byte k=4;
if(j>=0&&j<4){
byte l=0;
while((MESSAGE[i+k]!='&')&&(MESSAGE[i+k]!=' ')&&(MESSAGE[i+k]!='\n')&&(MESSAGE[i+k]!='\r')&&(MESSAGE[i+k]!='\0')){
l=l*10+byte(MESSAGE[i+k]-'0');
k++;
}
switch(t){
case 1:
IP[j]=l;
EEPROM.write(EEPROM_IP+j,l);
break;
case 2:
SUBNET[j]=l;
EEPROM.write(EEPROM_SUBNET+j,l);
break;
case 3:
GATEWAY[j]=l;
EEPROM.write(EEPROM_GATEWAY+j,l);
break;
}
}
return(k);
}
byte getDigit(byte i,byte t)
{
byte k=4;
unsigned int l=0;
while((MESSAGE[i+k]!='&')&&(MESSAGE[i+k]!=' ')&&(MESSAGE[i+k]!='\n')&&(MESSAGE[i+k]!='\r')&&(MESSAGE[i+k]!='\0')){
l=l*10+byte(MESSAGE[i+k]-'0');
k++;
}
switch(t){
case 1:
PORT=l;
EEPROM.write(EEPROM_PORT,byte((PORT&0xff00)/256));
EEPROM.write(EEPROM_PORT+1,byte(PORT&0x00ff));
break;
case 2:
REFRESH=l;
EEPROM.write(EEPROM_REFRESH,byte((REFRESH&0xff00)/256));
EEPROM.write(EEPROM_REFRESH+1,byte(REFRESH&0x00ff));
break;
}
return(k);
}
void parseCGI()
{
byte i=0;
byte flag=false;
// Send to Digital pins from parse HTTP send message
while(MESSAGE!='\0'){
// Port Status
if((MESSAGE=='p'||MESSAGE=='P')&&(MESSAGE[i+2]=='=')){
digitalWrite(int(MESSAGE[i+1])-'0',int(MESSAGE[i+3])-'0');
i+=3;
}
// Page
if((MESSAGE=='g'||MESSAGE=='G')&&(MESSAGE[i+1]=='=')){
page=MESSAGE[i+2]-'0';
i+=2;
}
// Clear EEPROM to zero
if((MESSAGE=='c'||MESSAGE=='C')&&(MESSAGE[i+1]=='l'||MESSAGE[i+1]=='L')&&(MESSAGE[i+2]=='0')&&(MESSAGE[i+3]=='=')){
for(int j=0;j<512;j++){
EEPROM.write(EEPROM_START_ADDRESS+j,0);
}
i+=6;
}
// MAC Address Config and Write MAC to EEPROM
if((MESSAGE=='m'||MESSAGE=='M')&&(MESSAGE[i+1]=='a'||MESSAGE[i+1]=='A')&&(MESSAGE[i+3]=='=')){
byte j=MESSAGE[i+2]-'0';
if(j>=0&&j<6){
for(byte l=0;l<2;l++){
byte k=MESSAGE[i+4+l];
// Change to upper case
if(k>'Z'){
k=k-'a'+'A';
}
if(k<='9'&&k>='0'){
switch(l){
case 0:
MAC[j]=byte(int(k-'0')*16);
break;
case 1:
MAC[j]+=byte(int(k-'0'));
break;
}
}else{
switch(l){
case 0:
MAC[j]=byte(int(k-'A'+10)*16);
break;
case 1:
MAC[j]+=byte(int(k-'A'+10));
break;
}
}
}
EEPROM.write(EEPROM_MAC+j,MAC[j]);
}
i+=5;
}
// IP Address Config and Write to EEPROM
if((MESSAGE=='i'||MESSAGE=='I')&&(MESSAGE[i+1]=='p'||MESSAGE[i+1]=='P')&&(MESSAGE[i+3]=='=')){
i+=getIP(i,1);
}
// Subnet Address Config and Write to EEPROM
if((MESSAGE=='s'||MESSAGE=='S')&&(MESSAGE[i+1]=='b'||MESSAGE[i+1]=='B')&&(MESSAGE[i+3]=='=')){
i+=getIP(i,2);
}
// Gateway Address Config and Write to EEPROM
if((MESSAGE=='g'||MESSAGE=='G')&&(MESSAGE[i+1]=='w'||MESSAGE[i+1]=='W')&&(MESSAGE[i+3]=='=')){
i+=getIP(i,3);
}
// Port Config and Write to EEPROM
if((MESSAGE=='p'||MESSAGE=='P')&&(MESSAGE[i+1]=='r'||MESSAGE[i+1]=='R')&&(MESSAGE[i+2]=='0')&&(MESSAGE[i+3]=='=')){
i+=getDigit(i,1);
}
// Refresh Time Config and Write to EEPROM
if((MESSAGE=='r'||MESSAGE=='R')&&(MESSAGE[i+1]=='f'||MESSAGE[i+1]=='F')&&(MESSAGE[i+2]=='0')&&(MESSAGE[i+3]=='=')){
i+=getDigit(i,2);
}
// Switch default state Config and Write to EEPROM
if((MESSAGE=='s'||MESSAGE=='S')&&(MESSAGE[i+1]=='w'||MESSAGE[i+1]=='W')&&(MESSAGE[i+3]=='=')){
byte j=MESSAGE[i+2]-'0';
SW[j]=byte(MESSAGE[i+4]-'0');
EEPROM.write(EEPROM_SW+j,SW[j]);
i+=5;
}
i++;
}
}
void setup()
{
// Read/Write config from/to EEPROM
ReadWriteConfig();
// Initial digital pin setting to EEPROM store setting
for(byte i=0;i<PINS;i++){
pinMode(i,OUTPUT);
digitalWrite(i,SW);
}
}
void loop()
{
Server server=Server(PORT);
if(bootUp){
// Initial Ethernet MAC and IP setting
Ethernet.begin(MAC,IP,GATEWAY,SUBNET);
// Start server listen
server.begin();
bootUp=false;
}
/* Initial client */
Client client=server.available();
if(client) {
boolean current_line_is_blank=true,flag=false;
char c='\0';
byte i=0;
// If connected
while(client.connected()){
if(client.available()){
/* Clear MESSAGE */
for(i=0;i<LENGTH;i++){
MESSAGE='\0';
}
flag=false;
i=0;
// Read from HTTP GET input information
while((c=client.read())!='\n' && i<=LENGTH){
if(c=='?'){
flag=true;
}
if(c==' '||c=='\n'||c=='\0'){
flag=false;
}
if(flag){
MESSAGE[i++]=c;
}
}
MESSAGE='\0';
page=0;
parseCGI();
if(current_line_is_blank){
// Send HTTP header
get2RAM(5);
client.println(buffer);
//client.println("HTTP/1.1 200 OK");
get2RAM(6);
client.println(buffer);
//client.println("Content-Type: text/html; charset=utf-8");
client.println();
// Send HTML
get2RAM(7);
client.println(buffer);
//client.println("<html>");
get2RAM(9);
client.print(buffer);
//client.print("<title>");
get2RAM(0);
client.print(buffer);
//client.print(TITLE);
get2RAM(10);
client.println(buffer);
//client.println("</title>");
get2RAM(11);
//client.print("<head>");
client.print(buffer);
get2RAM(13);
client.print(buffer);
//client.print("<center>");
client.print("<h1>");
get2RAM(0);
client.print(buffer);
//client.print(TITLE);
client.print("</h1>");
get2RAM(14);
client.print(buffer);
//client.println("</center>");
get2RAM(15);
client.print(buffer);
//client.print("<meta http-equiv=\"refresh\" content=\"");
if(page==0){
client.print(REFRESH);
}else{
client.print(3600);
}
get2RAM(29);
client.print(buffer);
//client.println(";url=/\">");
get2RAM(12);
client.println(buffer);
//client.println("</head>");
get2RAM(16);
client.print(buffer);
//client.println("<body>");
client.println("<hr>");
get2RAM(28);
client.print(buffer);
//client.print("<form method=\"");
//client.print("GET");
//client.print("\"");
//client.println(" action=\"/\">");
if(page==0){
// Read data from digital pin
get2RAM(31);
client.print(buffer);
/*
client.print("<table border=\"");
client.print(1);
client.print("\"");
client.print(" ");
client.print("align=\"");
client.print("center");
client.print("\"");
client.println(">");
*/
get2RAM(30);
client.print(buffer);
/*
client.print("<tr>");
client.print("<td>");
client.print("Digital");
client.print(" ");
client.print("Pin");
client.print("</td>");
client.print("<td>");
client.print("On");
client.print("</td>");
client.print("<td>");
client.print("Off");
client.print("</td>");
client.println("</tr>");
*/
for(i=0;i<PINS;i++){
client.print("<tr><td>SW ");
client.print(int(i));
client.println("</td><td>");
/* Display pins status */
if(digitalRead(i)==HIGH){
get2RAM(45);
client.print(buffer);
client.print("p");
client.print(int(i));
get2RAM(53);
client.print(buffer);
//client.print("\" checked=\"checked");
client.print(1);
get2RAM(21);
client.print(buffer);
/*
client.print("<input type=radio");
client.print(" ");
client.print("name=\"");
client.print("p");
client.print(int(i));
client.print("\"");
client.print(" ");
client.print("checked");
client.print(" ");
client.print("value=\"");
client.print(1);
client.print("\">");
*/
client.println("</td>");
client.print("<td>");
get2RAM(45);
client.print(buffer);
client.print("p");
client.print(int(i));
get2RAM(19);
client.print(buffer);
client.print(0);
get2RAM(21);
client.print(buffer);
/*
client.print("<input type=radio");
client.print(" ");
client.print("name=\"");
client.print("p");
client.print(int(i));
client.print("\"");
client.print(" ");
client.print("value=\"");
client.print(0);
client.println("\">");
*/
}else{
get2RAM(45);
client.print(buffer);
client.print("p");
client.print(int(i));
get2RAM(19);
client.print(buffer);
client.print(1);
get2RAM(21);
client.print(buffer);
/*
client.print("<input type=radio");
client.print(" ");
client.print("value=\"");
client.print(1);
client.print("\"");
client.print(" ");
client.print("name=\"");
client.print("p");
client.print(int(i));
client.print("\">");
*/
client.println("</td>");
client.print("<td>");
get2RAM(45);
client.print(buffer);
client.print("p");
client.print(int(i));
get2RAM(53);
client.print(buffer);
//client.print("\" checked=\"checked");
get2RAM(19);
client.print(buffer);
client.print(0);
get2RAM(21);
client.print(buffer);
/*
client.print("<input type=radio");
client.print(" ");
client.print("checked");
client.print(" ");
client.print("value=\"");
client.print(0);
client.print("\"");
client.print(" ");
client.print("name=\"");
client.print("p");
client.print(int(i));
client.println("\">");
*/
}
get2RAM(47);
client.print(buffer);
//client.println("</td></tr>");
}
get2RAM(27);
client.print(buffer);
//client.print("</table>");
}
get2RAM(13);
client.print(buffer);
//client.print("<center>");
if(page==1){
get2RAM(32);
client.print(buffer);
/*
client.print("<a href=\"/?g=");
client.print(2);
client.print("\"");
client.print(">");
client.print("Config");
client.print(" ");
client.print("MAC Address");
client.print("</a>");
*/
client.println("<br>");
get2RAM(33);
client.print(buffer);
/*
client.print("<a href=\"/?g=");
client.print(3);
client.print("\"");
client.print(">");
client.print("Config");
client.print(" ");
client.print("IP Address");
client.print("</a>");
*/
client.println("<br>");
get2RAM(34);
client.print(buffer);
/*
client.print("<a href=\"/?g=");
client.print(4);
client.print("\"");
client.print(">");
client.print("Config");
client.print(" ");
client.print("Subnet Mask");
client.print("</a>");
*/
client.println("<br>");
get2RAM(35);
client.print(buffer);
/*
client.print("<a href=\"/?g=");
client.print(5);
client.print("\"");
client.print(">");
client.print("Config");
client.print(" ");
client.print("Gateway Address");
client.print("</a>");
*/
client.println("<br>");
get2RAM(36);
client.print(buffer);
/*
client.print("<a href=\"/?g=");
client.print(6);
client.print("\"");
client.print(">");
client.print("Config");
client.print(" ");
client.print("TCP Port");
client.print("</a>");
*/
client.println("<br>");
get2RAM(37);
client.print(buffer);
/*
client.print("<a href=\"/?g=");
client.print(7);
client.print("\"");
client.print(">");
client.print("Config");
client.print(" ");
client.print("HTML Refresh Time");
client.print("</a>");
*/
client.println("<br>");
get2RAM(48);
client.print(buffer);
client.println("<br>");
}
if(page>=2){
get2RAM(38);
client.print(buffer);
/*
client.print("<table border=\"");
client.print(0);
client.print("\"");
client.print(" ");
client.print("align=\"");
client.print("center");
client.print("\"");
client.print(">");
*/
if(page==2){
get2RAM(39);
client.print(buffer);
/*
client.println("<tr>");
client.print("<td>");
client.print("MAC Address");
client.println("</td>");
client.print("<td>");
*/
for(i=0;i<6;i++){
if(i>0&&i<6){
client.print(":");
}
get2RAM(18);
client.print(buffer);
client.print("ma");
client.print(int(i));
get2RAM(19);
client.print(buffer);
char2Hex(MAC);
client.print(buffer);
get2RAM(20);
client.print(buffer);
client.print(2);
get2RAM(21);
client.print(buffer);
}
client.println("</td>");
}
if(page==3){
get2RAM(40);
client.print(buffer);
/*
client.println("<tr>");
client.print("<td>");
client.print("IP Address");
client.println("</td>");
client.println("<td>");
*/
for(i=0;i<4;i++){
if(i>0&&i<4){
client.print(".");
}
get2RAM(18);
client.print(buffer);
client.print("ip");
client.print(int(i));
get2RAM(20);
client.print(buffer);
client.print(3);
get2RAM(19);
client.print(buffer);
client.print(int(IP));
get2RAM(21);
client.print(buffer);
}
get2RAM(47);
client.print(buffer);
//client.println("</td></tr>");
}
if(page==4){
get2RAM(41);
client.print(buffer);
/*
client.println("<tr>");
client.print("<td>");
client.print("Subnet Mask");
client.println("</td>");
client.println("<td>");
*/
for(i=0;i<4;i++){
if(i>0&&i<4){
client.print(".");
}
get2RAM(18);
client.print(buffer);
client.print("sb");
client.print(int(i));
get2RAM(20);
client.print(buffer);
client.print(3);
get2RAM(19);
client.print(buffer);
client.print(int(SUBNET));
get2RAM(21);
client.print(buffer);
}
get2RAM(47);
client.print(buffer);
//client.println("</td></tr>");
}
if(page==5){
get2RAM(42);
client.print(buffer);
/*
client.println("<tr>");
client.println("<td>");
client.print("Gateway");
client.println("</td>");
client.print("<td>");
*/
for(i=0;i<4;i++){
if(i>0&&i<4){
client.print(".");
}
get2RAM(18);
client.print(buffer);
client.print("gw");
client.print(int(i));
get2RAM(20);
client.print(buffer);
client.print(3);
get2RAM(19);
client.print(buffer);
client.print(int(GATEWAY));
get2RAM(21);
client.print(buffer);
}
get2RAM(47);
client.print(buffer);
//client.println("</td></tr>");
}
if(page==6){
get2RAM(43);
client.print(buffer);
/*
client.println("<tr>");
client.print("<td>");
client.print("TCP Port");
client.println("</td>");
client.println("<td>");
*/
get2RAM(18);
client.print(buffer);
client.print("pr");
client.print(0);
get2RAM(20);
client.print(buffer);
client.print(5);
get2RAM(19);
client.print(buffer);
client.print((unsigned int)int(PORT));
get2RAM(21);
client.print(buffer);
get2RAM(47);
client.print(buffer);
//client.println("</td></tr>");
}
if(page==7){
//client.println("<td>");
get2RAM(44);
client.print(buffer);
get2RAM(18);
client.print(buffer);
client.print("rf");
client.print(0);
get2RAM(20);
client.print(buffer);
client.print(3);
get2RAM(19);
client.print(buffer);
client.print((unsigned int)int(REFRESH));
get2RAM(21);
client.print(buffer);
get2RAM(47);
client.print(buffer);
//client.println("</td></tr>");
}
if(page==8){
get2RAM(49);
client.print(buffer);
get2RAM(51);
client.print(buffer);
//client.print("</td></tr><br><tr><td>");
get2RAM(38);
client.print(buffer);
get2RAM(52);
client.print(buffer);
//client.println("<tr><td></td><td>On/Off</td></tr>");
for(i=0;i<PINS;i++){
client.print("<tr><td>SW");
client.print(int(i));
client.print("</td><td>");
get2RAM(45);
client.print(buffer);
//client.print("<input type=\"radio\" name=\"sw");
client.print("sw");
client.print(int(i));
get2RAM(19);
client.print(buffer);
//client.print("\" value=\"");
client.print(1);
if(SW==1){
get2RAM(53);
client.print(buffer);
//client.print("\" checked=\"checked");
}
get2RAM(21);
client.print(buffer);
get2RAM(45);
client.print(buffer);
//client.print("<input type=\"radio\" name=\"sw");
client.print("sw");
client.print(int(i));
get2RAM(19);
client.print(buffer);
//client.print("\" value=\"");
client.print(0);
if(SW==0){
get2RAM(53);
client.print(buffer);
//client.print("\" checked=\"checked");
}
get2RAM(21);
client.print(buffer);
get2RAM(47);
client.print(buffer);
//client.println("</td></tr>");
}
get2RAM(27);
client.print(buffer);
//client.print("</table>");
get2RAM(47);
client.print(buffer);
//client.print("</td></tr>");
get2RAM(47);
client.print(buffer);
//client.println("</td></tr>");
}
get2RAM(27);
client.print(buffer);
//client.println("</table>");
client.println("<br>");
}
get2RAM(14);
client.print(buffer);
//client.println("</center>");
if(page>=2){
get2RAM(13);
client.print(buffer);
//client.println("<center>");
get2RAM(23);
client.print(buffer);
get2RAM(14);
client.print(buffer);
//client.println("</center>");
client.println("<br>");
}
if(page!=1){
get2RAM(13);
client.print(buffer);
//client.println("<center>");
get2RAM(22);
client.print(buffer);
get2RAM(14);
client.print(buffer);
//client.println("</center>");
}
get2RAM(46);
client.print(buffer);
//client.println("</form>");
client.println("<br>");
client.print("<hr>");
get2RAM(13);
client.print(buffer);
//client.print("<center>");
if(page==0){
get2RAM(26);
client.print(buffer);
}
if(page>=2){
get2RAM(25);
client.print(buffer);
}
if(page!=0){
get2RAM(24);
client.print(buffer);
}
get2RAM(14);
client.print(buffer);
//client.print("</center>");
client.println("<br>");
/*
// Debug received message
client.print("Message=");
client.println(MESSAGE);
for(i=0;i<16;i++){
client.print(int(EEPROM.read(EEPROM_START_ADDRESS+i)));
client.print(" ");
}
client.print("Page ");
client.println(int(page));
// Debug message end
*/
// HTML tail
client.println("<h6>");
get2RAM(2);
client.print(buffer);
client.print("<br>");
//client.println("Open source of hardware and software for Arduino";
client.print("<a href=");
get2RAM(4);
client.print(buffer);
//client.print("http://www.arduino.cc");
client.print(">");
get2RAM(4);
client.print(buffer);
//client.print("http://www.arduino.cc");
client.print("</a>");
client.print("<br>");
get2RAM(3);
client.println(buffer);
client.println("<br>");
client.println("</h6>");
get2RAM(17);
client.println(buffer);
//client.println("</body>");
get2RAM(8);
client.println(buffer);
//client.println("</html>");
break;
}
if(c=='\n'){
current_line_is_blank=false;
}
}
}
delay(1);
client.stop();
}
}
Arduino Ethernet Shield
12/02/2009, 17:15 - Open Source
花了一點時間,用了一下Arduino 這個小東西,Open source 的硬體和軟體。順便作了一個可以經由網路控制的數位腳,及SSR當作電源開關。這個程式加上了 Arduino Ethernet Shield 可以用 Arduino Ethernet Library 也可以換成 Ethernet2 Library,用 Ethernet2 空間會比較省。下次再配合 Arduino SD shield 看看吧!作起來比 Microship 的 PIC 簡單,程式工具不用錢,可以在Windows/Mac OS X/Linux 下寫程式,不必被限制一定要用Windows。不必買燒錄工具,用 USB 就可以寫入資料。不過在燒入資料時,digital pin 1 和 2 不可以接東西。目前 MAC address 和 IP 是固定的,有空再試試 DHCP library。
/*
This program is wor Arduino Ethernet Shield with W5100 ethernet chip,
As a 8 digital pins control in web page
Programmer : Tasuka Hsu, Dec 1 2009
*/
/* Library import */
#include <Ethernet2.h>
#include <Print.h>
#include <Server.h>
#include <Client.h>
/* Const define */
#define LENGTH 42 /* Message length */
#define PINS 8 /* Digital pins 1 to 8 */
#define PORT 80 /* HTTP port */
#define REFRESH 10 /* HTTP refresh timer */
/* MAC Address */
byte MAC[]={0x00,0x0c,0x01,0x01,0xef,0xff};
/* IP Address setting */
byte IP[]={172,16,7,251};
byte GATEWAY[]={172.16,7,254};
byte SUBNET[]={255,255,255,248};
/* HTTP Server setting */
Server server=Server(PORT);
char TITLE[]="Adruino Digital Pins Control";
char MESSAGE[LENGTH+1];
void setup()
{
/* Initial Ethernet MAC and IP setting */
Ethernet.begin(MAC,IP,GATEWAY,SUBNET);
/* Initial digital pin setting to default 0 */
for(int i=0;i<PINS;i++){
pinMode(i,OUTPUT);
digitalWrite(i,0);
}
/* Start server listen */
server.begin();
}
void loop()
{
/* Initial client */
Client client=server.available();
if(client) {
boolean current_line_is_blank=true,flag=false;
char c='\0';
int i=0;
/* If connected */
while(client.connected()){
if(client.available()){
/* Clear MESSAGE */
for(i=0;i<LENGTH;i++){
MESSAGE='\0';
}
flag=false;
i=0;
/* Read from HTTP GET input information */
while((c=client.read())!='\n' && i<=LENGTH){
if(c=='?'){
flag=true;
}
if(c==' '||c=='\n'||c=='\0'){
flag=false;
}
if(flag){
MESSAGE[i++]=c;
}
}
MESSAGE='\0';
i=0;
flag=false;
/* Send to Digital pins from parse HTTP send message */
while(MESSAGE!='\0'){
if((MESSAGE=='p'||MESSAGE=='P')&&(MESSAGE[i+2]=='=')){
digitalWrite(int(MESSAGE[i+1])-0x30,int(MESSAGE[i+3])-0x30);
i+=3;
}
i++;
}
if(current_line_is_blank){
/* Send HTTP header */
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html; charset=utf-8");
client.println();
/* Send HTML */
client.print("<html>\n<title>");
client.print(TITLE);
client.print("</title>\n<head>\n<center><h1>");
client.print(TITLE);
client.print("</h1></center>\n");
client.print("<meta http-equiv=\"refresh\" content=\"");
client.print(REFRESH);
client.print(";url=/\">\n</head>\n<body>\n");
client.print("<hr>\n<form method=\"GET\" action=\"/\">\n");
/* Read data from digital pin */
client.print("<table border=\"1\">\n");
client.print("<tr><td>Digital Pin</td><td>On</td><td>Off</td></tr>\n");
for(i=0;i<8;i++){
client.print("\n<tr><td>Pin ");
client.print(i);
client.print("</td>\n<td>");
/* Display pins status */
if(digitalRead(i)==1){
client.print("<input type=radio checked value=1 name=\"p");
client.print(i);
client.print("\"></td>\n");
client.print("<td><input type=radio value=0 name=\"p");
client.print(i);
client.print("\">\n");
}else{
client.print("<input type=radio value=1 name=\"p");
client.print(i);
client.print("\"></td>\n");
client.print("<td><input type=radio checked value=0 name=\"p");
client.print(i);
client.print("\">\n");
}
client.print("</td></tr>\n");
}
client.print("</table>\n");
client.print("<br><input type=submit value=\"Send\"></form><br>\n");
/* Debug received message */
// client.print("Message=");
// client.println(MESSAGE);
/* HTML tail */
client.print("<h6>\nOpen source of hardware and software for Arduino\n<br>\n");
client.print("<a href=http://www.arduino.cc>http://www.arduino.cc</a></h6>\n");
client.print("</body>\n</html>\n");
break;
}
if(c=='\n'){
current_line_is_blank=false;
}
}
}
delay(1);
client.stop();
}
}
rpm2targz
09/16/2009, 13:26 - Open Source
我使用 Slackware Linux作為工作平台,但要找應用程式時,經常看到只有 Debian或是只有rpm的格式。今天要用Google Desktop時,就發現 Linux 版本,只有包裝成 rpm 及 deb,所以就想到用 rpm2targz/rpm2tgz 這個工具轉檔一下,再自已搬到 /usr 下,就可以用了。為何最簡單的格式反而沒有人要用呢?好讀 PDB 檔案轉 TXT
09/07/2009, 16:37 - Open Source
因為想要用 BeBook電子書讀一些從好讀網站的繁體中文電子書。但好讀的檔案格式是用Palm Pilot 的 pdb 格式,BeBook正好就沒有支援pdb,也沒有好的轉換程式可以在Macintosh及Linux上作pdb至text的檔案轉換,用過pdb2txt,但是中文好像有問題,所以呢?男子漢要看電子書就自已作個轉換程式吧。 程式非常簡單,所以就不加說明了。這個程式可以將好讀的電子書轉成純文字格式,並將原來直式的標點符號改成橫式,其他的像是章節分段等好像用不到,所以就不管了。網路上說好讀的格式有加密,不過現在看來是沒有,只是加 pdb的表頭及分段而已。這個程式應該可以用任何版本的 C compiler,若要大量轉換的話,請自已作個 batch script吧。
/*
Translate Palm Document pdb to text in zh_TW.Big5
Programmer : Tasuka Hsu
Date : 2009/Sep/04
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define DoubleWord(a) \
a[0]*256*256*256+ \
a[1]*256*256+ \
a[2]*256+ \
a[3]
#define SingleWord(a) \
a[0]*256+a[1]
struct pdbHeader {
unsigned char name[32];
unsigned char attributes[2];
unsigned char version[2];
unsigned char creationDate[4];
unsigned char modificationDate[4];
unsigned char lastBackupDate[4];
unsigned char modificationNumber[4];
unsigned char appInfoID[4];
unsigned char sortInfoID[4];
unsigned char type[4];
unsigned char creator[4];
unsigned char uniqueIDseed[4];
unsigned char nextRecordListID[4];
unsigned char numberOfRecords[2];
} PDB;
int main(int argc, char *argv[])
{
FILE *fp;
int i=0,j=0;
unsigned char c;
char *filename;
if(argc>=2){
filename=(char *)malloc(sizeof(char)*(strlen(argv[1])+1));
strcpy(filename,argv[1]);
}else{
printf("PDB Filename is required.\n");
return(1);
}
if((fp=fopen(filename,"r"))==NULL){
printf("Can not open %s file\n",argv[1]);
return(1);
}
while(!feof(fp)){
c=fgetc(fp);
if(i<32)
PDB.name=c;
if(i>=32 && i<34)
PDB.attributes[i-32]=c;
if(i>=34 && i<36)
PDB.version[i-34]=c;
if(i>=36 && i<40)
PDB.creationDate[i-36]=c;
if(i>=40 && i<44)
PDB.modificationDate[i-40]=c;
if(i>=44 && i<48)
PDB.lastBackupDate[i-44]=c;
if(i>=48 && i<52)
PDB.modificationNumber[i-48]=c;
if(i>=52 && i<56)
PDB.appInfoID[i-52]=c;
if(i>=56 && i<60)
PDB.sortInfoID[i-56]=c;
if(i>=60 && i<64)
PDB.type[i-60]=c;
if(i>=64 && i<68)
PDB.creator[i-64]=c;
if(i>=68 && i<72)
PDB.uniqueIDseed[i-68]=c;
if(i>=72 && i<76)
PDB.nextRecordListID[i-72]=c;
if(i>=76 && i<78)
PDB.numberOfRecords[i-76]=c;
if(i>=78 && i<78+(SingleWord(PDB.numberOfRecords)*8));
if(i>=78+(SingleWord(PDB.numberOfRecords)*8)){
if(c!=0x0d){
if(c==0x1b)
c=0x0a;
if(c==0x00){
c=0x0a;
printf("\n");
j--;
}
if(c==0xa1){
i++;
printf("%c",c);
c=0;
if(!feof(fp)){
switch(c=fgetc(fp)){
case 0x55:c=0x56;break;
case 0x56:c=0x55;break;
case 0x57:c=0x58;break;
case 0x58:c=0x57;break;
case 0x59:c=0x5a;break;
case 0x5a:c=0x59;break;
case 0x5b:c=0x5c;break;
case 0x5c:c=0x5b;break;
case 0x5d:c=0x5f;break;
case 0x5e:c=0x60;break;
case 0x5f:c=0x5d;break;
case 0x60:c=0x5e;break;
case 0x61:c=0x63;break;
case 0x62:c=0x64;break;
case 0x63:c=0x61;break;
case 0x64:c=0x62;break;
case 0x65:c=0x67;break;
case 0x66:c=0x68;break;
case 0x67:c=0x65;break;
case 0x68:c=0x66;break;
case 0x69:c=0x6b;break;
case 0x6a:c=0x6c;break;
case 0x6b:c=0x69;break;
case 0x6c:c=0x6a;break;
case 0x6d:c=0x6f;break;
case 0x6e:c=0x70;break;
case 0x6f:c=0x6d;break;
case 0x70:c=0x6e;break;
case 0x71:c=0x73;break;
case 0x72:c=0x74;break;
case 0x73:c=0x71;break;
case 0x74:c=0x72;break;
case 0x75:c=0x77;break;
case 0x76:c=0x78;break;
case 0x77:c=0x75;break;
case 0x78:c=0x76;break;
case 0x79:c=0x7b;break;
case 0x7a:c=0x7c;break;
case 0x7b:c=0x79;break;
case 0x7c:c=0x7a;break;
case 0x7d:c=0x5f;break;
case 0x7e:c=0x60;break;
case 0x1b:c=0x0a;break;
case 0xa1:ungetc(c,fp);c=0;i--;break;
default:break;
}
}
}
if(c!=0)
printf("%c",c);
}else {
j++;
}
}
i++;
}
printf("\n");
fclose(fp);
printf("\n\nFilename : %s\n",filename);
printf("\nPDB Header\n");
printf("Name : %s\n",PDB.name);
printf("Attributes : %d\n",SingleWord(PDB.attributes));
printf("Version : %d\n",SingleWord(PDB.version));
printf("Creation date : %ds\n",DoubleWord(PDB.creationDate));
printf("Modification date : %ds\n",DoubleWord(PDB.modificationDate));
printf("Last backup date : %ds\n",DoubleWord(PDB.lastBackupDate));
printf("Modification number : %d\n",DoubleWord(PDB.modificationNumber));
printf("Application Info ID : %d\n",DoubleWord(PDB.appInfoID));
printf("Sort Info ID : %d\n",DoubleWord(PDB.sortInfoID));
printf("Type : %d\n",DoubleWord(PDB.type));
printf("Unique ID Seed : %d\n",DoubleWord(PDB.uniqueIDseed));
printf("Next Record List ID : %d\n",DoubleWord(PDB.nextRecordListID));
printf("Number of records : %d\n",SingleWord(PDB.numberOfRecords));
printf("File Size : %d bytes\n",i-78-(SingleWord(PDB.numberOfRecords)*8)-j);
free(filename);
return(0);
}
有了這個程式就可以用 BeBook 的電子紙看書,而不用再用小小的 iPod Touch 看小小的字了。
下次再來作個修改文章的程式給Macintosh用吧,前提是如果我想要作的話。
某家 DVR 破解
04/16/2009, 22:25 - Open Source
因朋友的硬體需求,需要將原來的監視系統換至不同的機器,但原來的 DVR 系統是放在 Flash 的 IDE 硬碟中,不是很方便,所以就花了一點時間,將系統直接裝到硬碟中。先用有 grub 的 Live CD 開機
準備好新的硬碟
fdisk /dev/hdb
建兩個 partition,因為 Flash IDE HDD 只有 64MB,而第一個 partition 只是用來放系統設定,所不用太大,而第二個就是 64MB 減去第一個 partition 的大小就可以了。
mke2fs /dev/hdv1
mke2fs /dev/hdb2
mkdir /mnt/hdb1
mkdir /mnt/hdb2
mount /dev/hdb1 /mnt/hdb1
mount /dev/hdb2 /mnt/hdb2
把 Flash IDE disk mount 起來,準備 copy
mount /dev/hda1 /mnt/hda1
mount /dev/hda2 /mnt/hda2
cp -ifR /mnt/hda1/* /mnt/hdb1/.
cp -ifR /mnt/hdb2/* /mnt/hdb2/.
用 grub 建立 boot
grub
root (hd1,1)
setup (hd1)
修改 Linux 開機 root directory 的設定
/mnt/hdb2/etc/fstab
/mnt/hdb/boot/grub/menu.lst
將 Live CD 移除,重開機。
就可以了。
下次再試試改成光碟開機。
GNUstep on MS-Windows test
04/01/2009, 10:58 - Open Source
測試了一下 GNUstep 在 Windows 上的可行性,可以用,不過因為 DLL 等問題,要作到 portable 還很不方便。選用 MinGW32 作為基礎,再加裝需要的程式上去。
Install GNUstep in MS-Windows with MinGW
This required a long time in Windows, so make a cup of tea or coffee or some beer as well.
Start: install MinGW binary from http://mingw.sf.net
install MinGW
install MSYS
install MSYSDTS
unarchive MSYSCORE
open MSYS shell
export CFLAGS="-I/usr/include -L/usr/lib"
export CXXFLAGS=$CFLAGS
export CPPFLAGS=$CFLAGS
Install required library
install ffcall
./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var --enable-threads --enable-shared --enable-ipv6 --disable-nls --disable-debug --with-gnu-ld
make
make install
install libffi
./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var --enable-threads --enable-shared --enable-ipv6 --disable-nls --disable-debug --with-gnu-ld
make
make install
install libiconv-1.9.2
./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var --enable-threads --enable-shared --enable-ipv6 --disable-nls --disable-debug --with-gnu-ld --enable-static
make
make install
install zlib
./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var
make
make install
install libxml2
./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var --enable-threads --enable-shared --enable-ipv6 --disable-nls --disable-debug --with-gnu-ld --enable-static --with-zlib=/usr
make
make install
install libxslt
./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var --enable-threads --enable-shared --enable-ipv6 --disable-nls --disable-debug --with-gnu-ld --enable-static
make
make install
install gettext-0.17
./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var --enable-threads --enable-shared --enable-static --enable-ipv6 --disable-nls --disable-debug --with-gnu-ld --enable-cxx --enable-threads=win32 --with-libiconv-prefix=/usr
make
After show the gettext-tools has error
cd gettext-0.17
cd gettext-runtime
make install
This step is only install the gettext runtime library include libintl, and the gettext-tools has "can not found iconv.h" in "gnulib-lib/libxml/encoding.h", so...
cd gettext-tools
cp /usr/include/iconv.h .
make
cd ..
make
install jpeg-6b
./configure --prefix=/usr --enable-shared --enable-static
make
make install
install tiff
./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var --enable-threads --enable-shared --enable-ipv6 --disable-nls --enable-static --disable-debug --with-gnu-ld --disable-jpeg
make
make install
install libpng-1.2.35
vi configure
search a line
/ac_cv_lib_z_zlibVersion=no
change no to yes
ac_cv_lib_z_zlibVersion=yes
./configure --prefix=/usr --enable-shared --enable-static
vi Makefile
change
LIBS = -lz
to
LIBS = -L/usr/lib -lz
change
CFLAGS = -g -O2
to
CFLAGS = -g -O2 -I/usr/include
make
make install
install sqlite
./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var --enable-threads --enale-shared --enable-static --disable-debug --disable-nls --with-gnu-ld
make
make install
install wxWidgets
./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var --enable-threads --enale-shared --enable-static --disable-debug --disable-nls --with-gnu-ld --enable-gui -enable-monolithic --enable-plugins --enable-objc_uniquifying --enable-compat26 --enable-intl --with-msw --enable-unicode --enable-offical_build
make
make install
install gdb-6.8
./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var --enable-threads --enale-shared --enable-static --disable-debug --disable-nls --with-gnu-ld --enable-obj-gc
make
make install
Download GNUstep source from http://www.gnustep.org
install gnustep-make
./configure --prefix=/usr/GNUstep --sysconfdir=/etc --localstatedir=/var --enable-threads --enable-shared --enable-ipv6 --disable-nls --disable-debug --with-gnu-ld
make
make install
vi /etc/profile
add under lines to file /etc/profile
export GNUSTEP_MAKEFILES=/usr/GNUstep/System/Library/Makefiles
export PATH=$PATH:/usr/GNUstep/System/Tools:/usr/GNUstep/Local/Tools:/usr/GNUstep/bin
export CFLAGS="-I/usr/include -I/usr/GNUstep/System/Library/Headers -I/usr/GNUstep/Local/Library/Headers -L/lib -L/usr/lib -L/usr/local/lib -L/usr/GNUstep/System/Library/Libraries -L/usr/GNUstep/Local/Library/Libraries"
source /etc/profile
chmod 755 /usr/GNUstep/System/Library/Makefiles/GNUstep.sh
/usr/GNUstep/System/Library/Makefiles/GNUstep.sh
install gnustep-objc
./configure --prefix=/usr/GNUstep --sysconfdir=/etc --localstatedir=/var --enable-threads --enable-shared --enable-static --enable-ipv6 --disable-nls --disable-debug --with-gnu-ld
make
make install
check /etc/GNUstep/GNUstep.conf
# This is the GNUstep configuration file.
# Any line starting with a '#' is a comment.
# Empty lines are ignored.
# Every other line in this file must be of the form
# XXX=YYY
# where there should be no spaces around the '=' (this is because we
# include this file in shell scripts and makefiles, and sh syntax
# requires no spaces around the '=').
#
# Standard sh quotes can be used in YYY but only at runtime; they can
# not be used while building.
# GNUstep can use up to 4 domains at the same time. They are System,
# Local, Network and User. You can install your programs / resources
# in any of these domains. This file mostly deals with configuring
# how the domains map to your filesystem.
# IMPORTANT: Don't delete lines from this file unless you want
# the values hardcoded in the packages to be used. If you want
# to suppress the network domain, set all its paths to be the same
# as the system domain. If you want to suppress the local domain,
# set all its paths to be the same as the network domain. If you
# want to suppress the user domain, set its paths to be the same
# as the local domain. You can not suppress the system domain.
# The paths should not include a '/' at the end.
# These GNUSTEP_*_ROOT variables are obsolete, and will be removed.
GNUSTEP_SYSTEM_ROOT=/usr/GNUstep/System
GNUSTEP_LOCAL_ROOT=/usr/GNUstep/Local
GNUSTEP_NETWORK_ROOT=/usr/GNUstep/Network
# The name of the user config file. This file can override
# some settings in this file. Usually used by users that want
# to install things into their GNUstep user domain and/or have
# many such domains.
GNUSTEP_USER_CONFIG_FILE=.GNUstep.conf
# The name of the user directory, if any. This is obsolete,
# and will be removed.
GNUSTEP_USER_DIR=GNUstep
# The name of the user directory where defaults (eg, preferences) are
# stored. If it does not start with a '/', it will be considered
# relative to the user home directory.
GNUSTEP_USER_DEFAULTS_DIR=GNUstep/Defaults
# This is where the gnustep-make Makefiles are installed.
# Traditionally, this is /usr/GNUstep/System/Library/Makefiles
#GNUSTEP_MAKEFILES=/usr/GNUstep/share/GNUstep/Makefiles
GNUSTEP_MAKEFILES=/usr/GNUstep/System/Library/Makefiles
# This is where the user home directories are. Only used to provide
# NSUserDirectory in gnustep-base. Never used anywhere else.
GNUSTEP_SYSTEM_USERS_DIR=/home
GNUSTEP_NETWORK_USERS_DIR=/home
GNUSTEP_LOCAL_USERS_DIR=/home
# This is where System GUI Applications get installed.
# Traditionally it is /usr/GNUstep/System/Applications.
#GNUSTEP_SYSTEM_APPS=/usr/GNUstep/lib/GNUstep/Applications
GNUSTEP_SYSTEM_APPS=/usr/GNUstep/System/Applications
# This is where System GUI Applications that only the
# Administrator can use get installed.
# Traditionally it is /usr/GNUstep/System/Applications/Admin.
#GNUSTEP_SYSTEM_ADMIN_APPS=/usr/GNUstep/lib/GNUstep/Applications
GNUSTEP_SYSTEM_ADMIN_APPS=/usr/GNUstep/System/Applications/Admin
# This is where System Web Applications (GSWeb, SOPE) get
# installed.
# Traditionally it is /usr/GNUstep/System/Library/WebApplications.
#GNUSTEP_SYSTEM_WEB_APPS=/usr/GNUstep/lib/GNUstep/WebApplications
GNUSTEP_SYSTEM_WEB_APPS=/usr/GNUstep/System/Library/WebApplications
# This is where System Command-Line Tools get installed.
# Traditionally it is /usr/GNUstep/System/Tools.
#GNUSTEP_SYSTEM_TOOLS=/usr/GNUstep/bin
GNUSTEP_SYsTEM_TOOLS=/usr/GNUstep/System/Tools
# This is where System Command-Line Tools that only the
# Administrator can use get installed. Important: this
# should not be in the PATH of normal users.
# Traditionally it is /usr/GNUstep/System/Tools/Admin.
#GNUSTEP_SYSTEM_ADMIN_TOOLS=/usr/GNUstep/sbin
GNUSTEP_SYSTEM_ADMIN_TOOLS=/usr/GNUstep/System/Tools/Admin
# This is where System resources get installed. This directory will
# contain a lot of executable code since *step traditionally likes to
# bundle executables and resources together.
# Traditionally it is /usr/GNUstep/System/Library.
#GNUSTEP_SYSTEM_LIBRARY=/usr/GNUstep/lib/GNUstep
GNUSTEP_SYSTEM_LIBRARY=/usr/GNUstep/System/Library
# This is where System headers get installed. They are the
# library .h headers.
# Traditionally it is /usr/GNUstep/System/Library/Headers.
#GNUSTEP_SYSTEM_HEADERS=/usr/GNUstep/include
GNUSTEP_SYSTEM_HEADERS=/usr/GNUstep/System/Library/Headers
# This is where System libraries get installed. By libraries we mean
# the shared/static object files that you can link into programs.
# Traditionally it is /usr/GNUstep/System/Library/Libraries.
#GNUSTEP_SYSTEM_LIBRARIES=/usr/GNUstep/lib
GNUSTEP_SYSTEM_LIBRARIES=/usr/GNUstep/System/Library/Libraries
# This is where System documentation get installed. This is known
# not to contain any executable, so we keep it separate.
# Traditionally it is /usr/GNUstep/System/Library/Documentation.
#GNUSTEP_SYSTEM_DOC=/usr/GNUstep/share/GNUstep/Documentation
GNUSTEP_SYSTEM_DOC=/usr/GNUstep/System/Library/Documentation
# This is where System man pages get installed.
# Traditionally it is /usr/GNUstep/System/Library/Documentation/man.
#GNUSTEP_SYSTEM_DOC_MAN=/usr/GNUstep/share/man
GNUSTEP_SYSTEM_DOC_MAN=/usr/GNUstep/System/Library/Documentation
# This is where System info pages get installed.
# Traditionally it is /usr/GNUstep/System/Library/Documentation/info.
#GNUSTEP_SYSTEM_DOC_INFO=/usr/GNUstep/share/info
GNUSTEP_SYSTEM_DOC_INFO=/usr/GNUstep/System/Library/Documentation/info
GNUSTEP_NETWORK_APPS=/usr/GNUstep/Network/Applications
GNUSTEP_NETWORK_ADMIN_APPS=/usr/GNUstep/Network/Applications
GNUSTEP_NETWORK_WEB_APPS=/usr/GNUstep/Network/WebApplications
GNUSTEP_NETWORK_TOOLS=/usr/GNUstep/Network/Tools
GNUSTEP_NETWORK_ADMIN_TOOLS=/usr/GNUstep/Network/Admin
GNUSTEP_NETWORK_LIBRARY=/usr/GNUstep/Network/Library
GNUSTEP_NETWORK_HEADERS=/usr/GNUstep/Network/Library/Headers
GNUSTEP_NETWORK_LIBRARIES=/usr/GNUstep/Network/Library/Libraries
GNUSTEP_NETWORK_DOC=/usr/GNUstep/Network/Documentation
GNUSTEP_NETWORK_DOC_MAN=/usr/GNUstep/Nework/Documentation/man
GNUSTEP_NETWORK_DOC_INFO=/usr/GNUstep/Network/Documentation/info
GNUSTEP_LOCAL_APPS=/usr/GNUstep/Local/Applications
GNUSTEP_LOCAL_ADMIN_APPS=/usr/GNUstep/Local/Applications/Admin
GNUSTEP_LOCAL_WEB_APPS=/usr/GNUstep/Local/Applications/WebApplications
GNUSTEP_LOCAL_TOOLS=/usr/GNUstep/Local/Tools
GNUSTEP_LOCAL_ADMIN_TOOLS=/usr/GNUstep/Tools/Admin
GNUSTEP_LOCAL_LIBRARY=/usr/GNUstep/Local/Library
GNUSTEP_LOCAL_HEADERS=/usr/GNUstep/Local/Library/Headers
GNUSTEP_LOCAL_LIBRARIES=/usr/GNUstep/Local/Library/Libraries
GNUSTEP_LOCAL_DOC=/usr/GNUstep/Local/Documentation
GNUSTEP_LOCAL_DOC_MAN=/usr/GNUstep/Local/Documentations/man
GNUSTEP_LOCAL_DOC_INFO=/usr/GNUstep/Local/Documentations/info
# Important: settings in the User should normally be relative paths,
# and will be interpreted as relative to the user's directory. This
# allows each user to have their own domain to install things. You
# can set them to be absolute, mostly if you want to disable them
# by setting them equal to the ones in the Network domain.
GNUSTEP_USER_DIR_APPS=GNUstep/Applications
GNUSTEP_USER_DIR_ADMIN_APPS=GNUstep/Applications/Admin
GNUSTEP_USER_DIR_WEB_APPS=GNUstep/WebApplications
GNUSTEP_USER_DIR_TOOLS=GNUstep/Tools
GNUSTEP_USER_DIR_ADMIN_TOOLS=GNUstep/Tools/Admin
GNUSTEP_USER_DIR_LIBRARY=GNUstep/Library
GNUSTEP_USER_DIR_HEADERS=GNUstep/Library/Headers
GNUSTEP_USER_DIR_LIBRARIES=GNUstep/Library/Libraries
GNUSTEP_USER_DIR_DOC=GNUstep/Library/Documentation
GNUSTEP_USER_DIR_DOC_MAN=GNUstep/Library/Documentation/man
GNUSTEP_USER_DIR_DOC_INFO=GNUstep/Library/Documentation/info
cd /usr/GNUstep/System/Library/Libraries
ln -s /usr/lib/libxml2.a .
ln -s /usr/lib/libxml2.la .
ln -s /usr/lib/libxml2.dll.a .
ln -s /usr/lib/libxslt.a .
ln -s /usr/lib/libxslt.la .
ln -s /usr/lib/libiconv.a .
ln -s /usr/lib/libiconv.la .
ln -s /usr/lib/libiconv.dll.a .
ln -s /usr/lib/libcallback.a .
ln -s /usr/lib/libcallback.la .
ln -s /usr/lib/libavcall.a .
ln -s /usr/lib/libavcall.la .
link others library in /usr/lib to /usr/GNUstep/System/Library/Libraries
install gnustep-base
./configure --prefix=/usr/GNUstep --sysconfdir=/etc --localstatedir=/var --enable-threads --enable-shared --enable-ipv6 --enable-nls --enable-static --disable-debug --with-gnu-ld --enable-pass-arguments --enable-ffcall --disable-ffi --disable-xml
install gnustep-gui
./configure --prefix=/usr/GNUstep --sysconfdir=/etc --localstatedir=/var --enable-threads --enable-shared --enable-ipv6 --enable-nls --enable-static --disable-debug --with-gnu-ld --with-jpeg-library=/usr/lib --with-jpeg-include=/usr/include
make
make install
install gnustep-back
./configure --prefix=/usr/GNUstep --sysconfdir=/etc --localstatedir=/var --enable-threads --enable-shared --enable-ipv6 --enable-nls --enable-static --disable-debug --with-gnu-ld --enable-graphics=winlib --enable-server=win32
make
make install
install Performance
make
make install
Install DevelopmentTool
install gorm
make
make install
install ProjectCenter
make
make install
install GWorkspace
./configure --prefix=/usr/GNUstep --enable-shared --enable-static
make
make install
寫了個簡單的程式 test1.m 測試一下。
#import <Foundation/Foundation.h>
int main(int argc, char *argv[])
{
NSAutoreleasePool *pool=[[NSAutoreleasePool alloc] init];
register unsigned int j,k;
NSString *s=[[NSString alloc] init];
NSNumber *i=[[NSNumber alloc] init];
NSMutableArray *table=[[NSMutableArray alloc] init];
s=[NSString stringWithString:@"This is a book!"];
i=[NSNumber numberWithInt:10];
NSLog(@"argc=%d",argc);
for(j=0;j<argc;j++){
[table addObject:[NSString stringWithCString:argv[j]]];
NSLog(@"argv[%d]=%@",j,[NSString stringWithCString:argv[j]]);
}
NSLog(@"i=%d s=%s",i,s);
#ifndef DARWIN
NSLog(@"i=%d s=%s",[i intValue],[s cString]);
#else
NSLog(@"i=%d s=%@",[i intValue],s);
#endif
if((k=[[NSString stringWithCString:argv[1]] intValue])<=0)
k=5;
NSLog(@"k=%d",k);
for(j=0;j<k;j++){
i=[NSNumber numberWithInt:j];
NSLog(@"j=%d i=%@",j,i);
}
[s retain];
[i retain];
[table retain];
[pool release];
return 0;
}
這個 Makefile 可以在有裝 XCode 的 OS X 或 Linux 裝 GNUstep 及 MS-Windows 裝 MinGW 下使用。
#
CC=gcc
#
OS_VERSION=$(shell uname -s)
CFLAGS=-I/usr/include -L/usr/lib
#
ifeq ($(OS_VERSION),Darwin)
export CFLAGS+=-DDARWIN -framework Foundation
else
GNUSTEP_DIR=/usr/GNUstep
GNUSTEP_SYSTEM_DIR=$(GNUSTEP_DIR)/System
GNUSTEP_LOCAL_DIR=$(GNUSTEP_DIR)/Local
#
export CFLAGS+=-I$(GNUSTEP_SYSTEM_DIR)/Library/Headers
export CFLAGS+=-I$(GNUSTEP_LOCAL_DIR)/Library/Headers
export CFLAGS+=-L$(GNUSTEP_SYSTEM_DIR)/Library/Libraries
export CFLAGS+=-L$(GNUSTEP_LOCAL_DIR)/Library/Libraries
ifeq ($(OS_VERSION),MINGW32_NT-5.1)
export CFLAGS+=-L/mingw/lib
export LIBS+=$(GNUSTEP_SYSTEM_DIR)/Library/Libraries/libobjc.dll.a
export LIBS+=$(GNUSTEP_LOCAL_DIR)/Library/Libraries/libgnustep-base.dll.a
export LDFLAGS+="-Wl,--enable-auto-import"
else
export CFLAGS+=-lgnustep-base -lobjc
endif
export CFLAGS+=-fconstant-string-class=NSConstantString
# For GCC-4.0 and upper only
# export CFLAGS+=-fobjc-call-cxx-cdtors
export CFLAGS+=-static-libgcc
endif
export CFLAGS+=-lstdc++
all:
$(CC) $(LDFLAGS) $(CFLAGS) test1.m $(LIBS) -o test1
clean:
rm -fr *.o *.exe
rm -fr test1
不過看來離我要的東西,還很遠。
對了 GNUstep 的 Gorm.app 就等於 XCode 的 Interface Builder 及 ProjectCenter.app 就是 XCode。
Android Source
03/03/2009, 02:59 - Open Source
跟著Android source download 用 repo 的方法一直會有 python 執行 import md5 需要改用 hashlist 的問題。所以就自已想了個辦法。先用 git 將 repo 同步回來,而不用 curl 。這樣就可以了。
cd ~
mkdir repo
cd repo
git clone git://android.git.kernel.org/tools/repo.git
cd ..
mkdir android
cd android
../repo/repo init -u git://android.git.kernel.org/platform/manifest.git
../repo/repo sync
就可以 download source code 及 make 了。
安裝 GNUstep 於 Linux 下
12/30/2008, 13:59 - Open Source
安裝 GNUstep 於 Linux 下至 http://www.gnustep.org 下載 source code
要 compile 之前要先確認是否有安裝 gcc 的 objc
gnustep-make
./configure --prefix=/usr/GNUstep --sysconfdir=/etc/GNUstep --localstatedir=/var/GNUstep --enable-threads --enable-shared --enable-ipv6 --disable-nls --disable-debug --with-gnu-ld --with-x --enable-multi-platform --enable-native-objc-exceptions
make install
export GNUSTEP_MAKEFILES=/usr/GNUstep/System/Library/Makefiles
export PATH=$PATH:/usr/GNUstep/System/Tools
gnustep-base
./configure --prefix=/usr/GNUstep --sysconfdir=/etc/GNUstep --localstatedir=/var/GNUstep --enable-threads --enable-shared --enable-ipv6 --disable-nls --disable-debug --with-gnu-ld --with-x
make
make install
export PATH=$PATH:/usr/GNUstep/Local/Tools
ln -s /usr/GNUstep/Local/Library/Libraries/libgnustep-base.so.1.18.0 /usr/lib/libgnustep-base.so.1.18.0
ln -s /usr/lib/libgnustep-base.so.1.18.0 /usr/lib/libgnustep-base.so.1.18
ln -s /usr/lib/libgnustep-base.so.1.18.0 /usr/lib/libgnustep-base.so
gnustep-gui
./configure --prefix=/usr/GNUstep --sysconfdir=/etc/GNUstep --localstatedir=/var/GNUstep --enable-threads --enable-shared --enable-ipv6 --disable-nls --disable-debug --with-gnu-ld --with-x
make
make install
ln -s /usr/GNUstep/Local/Library/Libraries/libgnustep-gui.so.0.16.0 /usr/lib/libgnustep-gui.so.0.16.0
ln -s /usr/lib/libgnustep-gui.so.0.16.0 /usr/lib/libgnustep-gui.so.0.16
ln -s /usr/lib/libgnustep-gui.so.0.16.0 /usr/lib/libgnustep-gui.so
gnustep-back
./configure --prefix=/usr/GNUstep --sysconfdir=/etc/GNUstep --localstatedir=/var/GNUstep --enable-threads --enable-shared --enable-ipv6 --disable-nls --disable-debug --with-gnu-ld --with-x
make
make install
Mac Mini 跑 Ubuntu 8.04.1
09/01/2008, 19:22 - Open Source
看來 Ubuntu 8.04 可以直接在 Intel 版本的 Mac mini 上跑,完全沒有問題,無線網路、藍牙、Gigabit Ethernet、音效、顯示卡,都沒有問題。接下來會試試 Gentoo Linux 吧,再決定要用那一種作為 Server ,原因是因為 Ubuntu 或者是 Slackware 這些已經 compile 好的 package 的內容都是以 ii486 為主 compile 出來的,效率可能會差一點點,而 Gentoo 是自已 compile 出來的,當然會比較會乎自已的機器。不過以安裝到可以用所花的時間來說 Gentoo 也需要最久,才可以裝好。也許可以試試 BSD看看!
這部 Mac mini 1.66GHz 是由一位正妹手中接過來的,保存得還很好,她好像只用來看 DVD及上網、跑 Windows。看來很多人看到了 Macintosh 後就下手買了,可是用了之後,又想還是要用 PC,或者是找不到想用軟體用,結果就讓我這種人常有二手機器可以買的機會。不過像我一部機器會用很久(平均在五年以上)的人可能也不太多吧!
接下來幾天,選定了 OS 版本,裝好應用程式,如 bind, apache, postfix,php, SimplePHPBlog 等等,應該就會上線,並將 Minitower 換下來了,到時可能也會將 IPv6 也放上來吧!















