2013-04-01 38 views
4

我有一個節點應用程序,它運行在覆蓋一堆UPnP播放器(Sonos)的樹莓派上,我希望能夠通過物理遙控器進行控制。我有幾個airmouses,有小鍵盤以及我想要使用的音量按鈕。是否有可能讀出node.js中的物理鍵盤筆劃?

我曾試圖獲得關於如何讀出物理按鍵敲擊在Linux機器上,並走到那我需要閱讀從輸入設備,事件結束一握它在我的情況是:

/dev/input/by-id/usb-Dell_Dell_QuietKey_Keyboard-event-kbd 

如何查找設備和類似的東西不是問題,真正的問題是如何解讀從中讀取的數據。

我知道你會得到一個C結構,像這樣:

struct input_event { 
    struct timeval time; 
    unsigned short type; 
    unsigned short code; 
    unsigned int value; 
}; 

但我不知道我怎麼會去從節點閱讀本。如果我可以運行一個外部應用程序,該應用程序可以通過預定義的擊鍵觸發,然後對我的節點調用HTTP請求,那麼這將是我的第二個選擇,即一個python腳本或一些本地守護程序。然而,我看了一些熱門的守護進程,但他們都沒有工作。

如果我能以某種方式將它包含在節點中,當然會很好。

編輯:所以,我做了一些測試,並做了一個簡單的代碼片段:

var fs = require('fs'); 

var buffer = new Buffer(16); 

fs.open('/dev/input/by-id/usb-HJT_Air_Mouse-event-kbd', 'r', function (err, fd) { 
    while (true) { 
     fs.readSync(fd, buffer, 0, 16, null); 
     console.log(buffer) 
    } 
}); 

這個輸出是這樣的(空間):

<Buffer a4 3e 5b 51 ab cf 03 00 04 00 04 00 2c 00 07 00> 
<Buffer a4 3e 5b 51 c3 cf 03 00 01 00 39 00 01 00 00 00> 
<Buffer a4 3e 5b 51 cb cf 03 00 00 00 00 00 00 00 00 00> 
<Buffer a4 3e 5b 51 ba 40 06 00 04 00 04 00 2c 00 07 00> 
<Buffer a4 3e 5b 51 cd 40 06 00 01 00 39 00 00 00 00 00> 
<Buffer a4 3e 5b 51 d2 40 06 00 00 00 00 00 00 00 00 00> 

我意識到,前四個字節某種時間戳,接下來的3個字節可能是微/毫秒的東西。另一個奇怪的事情是,並非所有的按鍵都會產生輸出,但隨後的按鍵可能會發送兩倍的數據,並且大多數時候它會開始播放在隨後的按鍵之後停止的數據(或大約20秒左右之後)。我不確定如何解釋這一點。我試圖讀取這個守護進程https://github.com/baskerville/shkd/blob/master的源代碼,但C並不是我最強的語言,我無法確定他是如何處理它的(或者甚至應該處理它)。而這個守護進程甚至沒有爲我工作(編譯它在一個覆盆子pi)。

回答

2

那麼,讓我們來看看這個結構。

struct input_event { 
    struct timeval time; 
    unsigned short type; 
    unsigned short code; 
    unsigned int value; 
}; 

一個struct timeval具有這樣的結構:

struct timeval 
    { 
    __time_t tv_sec;   /* Seconds. */ 
    __suseconds_t tv_usec;  /* Microseconds. */ 
    }; 

這些時間類型的定義是

typedef signed long time_t; 
typedef signed long suseconds_t; 

一個signed long爲4個字節(當然,不是如果你只是遵循規範,但實際上它是),所以前8個字節是一個類型戳。接下來,你有一個類型和一個代碼。兩者都是short,所以實際上,它們每個都是2個字節。現在只剩下值了,這又是一個int,它將是四個字節。另外,編譯器理論上可以在這些字段之間添加填充,但我確定他不會。

所以,首先砍你已經讀入的4+4+2+2+4=16字節的塊中的字節數。每個塊都是一個事件。這適合您的示例數據。接下來,從緩衝區中提取值(作爲小端值,因爲您在ARM系統上 - 在普通PC上,您需要大端值)並解釋值。有關如何操作的說明,請閱讀http://www.mjmwired.net/kernel/Documentation/input/event-codes.txt。常量的值不會寫在那裏,但通常可以找到那些使用grep -R NAME_OF_CONSTANT /usr/include的值。

讓我們砍了

<Buffer a4 3e 5b 51 ab cf 03 00 04 00 04 00 2c 00 07 00> 

作爲一個例子。

<Buffer a4 3e 5b 51 ab cf 03 00 04 00 04 00 2c 00 07 00> 
     | tv_sec | tv_usec |type |code | value | 

十六進制tv_sec0x515b3ea4(相反的順序,因爲它的小端),即十進制數1364934308。一個簡單的unix時間轉換器報告這意味着02.04.2013 - 22:25:08。看起來不錯!

tv_usec0x0003cfab=249771,所以實際上,事件發生在249771微秒之後。

類型是0x0004=4/usr/include/linux/input.h告訴我們這是一個EV_MSC

鑑於類型,我們也可以看到代碼,0x0004=4,意味着MSC_SCAN

值爲0x0007002c。在input.h中無處可逃。嗯。

+0

謝謝你,我已經在這裏找到了常量:http://tomoyo.sourceforge.jp/cgi-bin/lxr /source/include/uapi/linux/input.h和我就你的大小得出了類似的結論。然而,重複的事件是一個謎給我,以及我是否過濾掉不鍵入= 1和值= 0的一切,我通常會得到相應的鍵碼,但卻忽略了很多招。任何想法? – jishi

+0

@jishi:鍵是出現在一個正常的控制檯或等?可能是因爲你的鍵盤只有一塊電池沒電了。 :D – thejh

+0

感謝您的澄清。我想我可以放心地忽略MSC_SCAN條目。關於重複的代碼,看起來它是空中小屋的行爲,我無法複製戴爾有線鍵盤上的行爲。感謝您的反饋意見! – jishi

0

我想你要尋找的是fs.createReadStream,所以你可以安裝一些事件處理程序。

您可以通過使用Buffer.readX程序解析輸入事件到結構:

var i = 0; 
    while((buf.length-i) >= 16) { 
    var event = { 
     tssec: buf.readUInt32LE(i+0), 
     tsusec: buf.readUInt32LE(i+4), 
     type: buf.readUInt16LE(i+8), 
     code: buf.readUInt16LE(i+10), 
     value: buf.readUInt32LE(i+12) 
    }; 
    i += 16; 
    } 
相關問題