PHP код:
	
#include <OLED_I2C.h>
OLED  oled(SDA, SCL, 8);
extern uint8_t SmallFont[];
int IBUSreceiveByte = 0;
byte IBUSbyte[7] = {0,0,0,0,0,0,0};
int ButtonPressed = 0;
int KeyID = 0;
byte MINUS_DOWN[7] = {0, 0x50, 0x04, 0x68, 0x32, 0x10, 0x1E}; // - BUTTON PRESS
byte PLUS_DOWN[7] = {0, 0x50, 0x04, 0x68, 0x32, 0x11, 0x1F};  // + BUTTON PRESS
byte PREV_DOWN1[7] = {0, 0x50, 0x04, 0x68, 0x3B, 0x08, 0x0F}; // < BUTTON PRESS 1
byte PREV_DOWN2[7] = {0, 0x50, 0x04, 0xC8, 0x3B, 0x08, 0xAF}; // < BUTTON PRESS 2
byte NEXT_DOWN1[7] = {0, 0x50, 0x04, 0x68, 0x3B, 0x01, 0x06}; // > BUTTON PRESS 1
byte NEXT_DOWN2[7] = {0, 0x50, 0x04, 0xC8, 0x3B, 0x01, 0xA6}; // > BUTTON PRESS 2
byte VOICE_DOWN[7] = {0, 0x50, 0x04, 0xC8, 0x3B, 0x80, 0x27}; // VOICE BUTTON PRESS
byte RT_DOWN1[7] = {0, 0x50, 0x04, 0xFF, 0x3B, 0x00, 0x90};   // R/T BUTTON PRESS 1
byte RT_DOWN2[7] = {0, 0x50, 0x04, 0xFF, 0x3B, 0x40, 0xD0};   // R/T BUTTON PRESS 2
void setup() { 
  Serial1.begin(9600);
  oled.begin();
  oled.setFont(SmallFont);
  oled.print("BMW NEXUS 7", CENTER, 0);
  oled.print("Key:", LEFT, 20);
  oled.print("In   Load Hall 5v", LEFT, 45);
  oled.print("OFF  OFF  OFF  OFF", LEFT, 55);
  oled.update();
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, INPUT);
  pinMode(7, OUTPUT);
  digitalWrite(4, LOW);
  digitalWrite(5, LOW);
  digitalWrite(6, LOW);
  digitalWrite(7, LOW);
  Keyboard.begin();
  Media.begin();
  //Remote.begin();
  //System.begin();
} 
void loop() { 
  // вход
  if (digitalRead(6) == LOW) {
    PrintState("ON ", 0);
    digitalWrite(5, HIGH); // выход нагрузки
    PrintState("ON ", 30);
    digitalWrite(7, HIGH); // hall датчик
    PrintState("ON ", 60);
    digitalWrite(4, HIGH); // выход 5 вольт
    PrintState("ON ", 90);
  } else {
    PrintState("OFF", 0);   
    digitalWrite(5, LOW); // выход нагрузки
    PrintState("OFF", 30);
    digitalWrite(7, LOW); // hall датчик
    PrintState("OFF", 60);
    digitalWrite(4, LOW); // выход 5 вольт
    PrintState("OFF", 90);
  }
  // кнопки руля
  if (Serial1.available() && ButtonPressed == 0) {  
    TryReadIBUSmsg();
  }
  // нажата кнопка
  if (ButtonPressed == 1) {
    switch (KeyID) {
      case 100:  // если клавиша не  опознана или есть ошибки в шине при чтении
        Media.releaseAll();
        Keyboard.releaseAll();
        PrintKey("UNKNOWN key");
        PrintCode(); 
      break;
      case 1: 
        Media.write(MEDIA_VOLUME_UP);
        PrintKey("VOL + key");
        PrintCode(); 
      break;    
      case 2:
        Media.write(MEDIA_VOLUME_DOWN);
        PrintKey("VOL - key");
        PrintCode(); 
      break;
      case 11:
        Media.write(MEDIA_NEXT);
        PrintKey("NEXT TRACK key");
        PrintCode();  
      break;
      case 21:
        Media.write(MEDIA_PREVIOUS);
        PrintKey("PREV TRACK key");
        PrintCode(); 
      break;
      case 31:
        Media.write(MEDIA_PLAY_PAUSE);
        PrintKey("VOICE key");
        PrintCode(); 
      break;
      case 41:
        //Media.write(MEDIA_BROWSER_BACK);
        Keyboard.press(KEY_LEFT_ALT);
        Keyboard.press(KEY_TAB);
        Keyboard.release(KEY_TAB);
        Keyboard.press(KEY_TAB);
        Keyboard.release(KEY_TAB);
        PrintKey("R/T key");
        PrintCode(); 
      break;
    } 
    ButtonPressed = 0;
    Serial1.flush();
  }
  delay(10);
}
// чтение I-Bus шины
void TryReadIBUSmsg() {
  IBUSreceiveByte = Serial1.read();
  if (IBUSreceiveByte==0x50) { 
    IBUSbyte[1]=0x50;   
    for (int i=2; i<=6; i++) {   
      IBUSbyte[i] = Serial1.read();
      delay(10); 
    }
    KeyID=100;
    if(memcmp(IBUSbyte, PLUS_DOWN, 7) == 0)  { KeyID=1; } 
    if(memcmp(IBUSbyte, MINUS_DOWN, 7) == 0) { KeyID=2; } 
    if(memcmp(IBUSbyte, NEXT_DOWN1, 7) == 0) { KeyID=11; }
    if(memcmp(IBUSbyte, NEXT_DOWN2, 7) == 0) { KeyID=11; } 
    if(memcmp(IBUSbyte, PREV_DOWN1, 7) == 0) { KeyID=21; }
    if(memcmp(IBUSbyte, PREV_DOWN2, 7) == 0) { KeyID=21; }  
    if(memcmp(IBUSbyte, VOICE_DOWN, 7) == 0) { KeyID=31; } 
    if(memcmp(IBUSbyte, RT_DOWN1, 7) == 0 )  { KeyID=41; }
    if(memcmp(IBUSbyte, RT_DOWN2, 7) == 0 )  { KeyID=41; }
    ButtonPressed=1; 
  } else { 
    ButtonPressed=0; 
  }
  Serial1.flush(); 
}
// печатаем код из I-Bus
void PrintCode() {
  int x=0;
  for (int i=1; i<=6; i++) {
    oled.print(String(IBUSbyte[i],HEX), x, 30);
    x+=20;
  }
  oled.update();
}
void PrintKey(String text) {
  oled.print(text, 30, 20);
  oled.update();
}
void PrintState(String text, int x) {
  oled.print(text, x, 55);
  oled.update();
} 
 И 
	PHP код:
	
#define CHECK_MS 5 
#define DOUBLE_MS 400 
#define HOLD_MS 1200 
#define NO_B 839 //nothing pressed 
#define MODE_B 662 // MODE 
#define NXTU_B 509 // NEXT UP 
#define NXTD_B 380 // NEXT DOWN 
#define MUTE_B 273 // MUTE 
#define VOLU_B 180 // VOLUME UP 
#define VOLD_B 105 // VOLUME DOWN 
#define alpPin 7 
boolean volUp[48] = {1,1,0,1,0,1,1,1, 1,1,0,1,1,0,1,1, 1,0,1,0,1,0,1,1, 1,1,0,1,1,0,1,1, 1,1,0,1,0,1,1,0, 1,1,0,1,0,1,0,1}; 
boolean volDn[48] = {1,1,0,1,0,1,1,1, 1,1,0,1,1,0,1,1, 1,0,1,0,1,0,1,1, 0,1,1,0,1,1,0,1, 1,1,1,1,0,1,1,0, 1,1,0,1,0,1,0,1}; 
boolean mute[48] = {1,1,0,1,0,1,1,1, 1,1,0,1,1,0,1,1, 1,0,1,0,1,0,1,1, 1,0,1,0,1,1,0,1, 1,1,1,0,1,1,1,0, 1,1,0,1,0,1,0,1}; 
boolean pstUp[48] = {1,1,0,1,0,1,1,1, 1,1,0,1,1,0,1,1, 1,0,1,0,1,0,1,1, 1,0,1,0,1,0,1,1, 1,1,1,0,1,1,1,1, 0,1,0,1,0,1,0,1}; 
boolean pstDn[48] = {1,1,0,1,0,1,1,1, 1,1,0,1,1,0,1,1, 1,0,1,0,1,0,1,1, 0,1,0,1,0,1,0,1, 1,1,1,1,1,1,1,1, 0,1,0,1,0,1,0,1}; 
boolean source[48] = {1,1,0,1,0,1,1,1, 1,1,0,1,1,0,1,1, 1,0,1,0,1,0,1,1, 1,0,1,1,0,1,1,1, 1,1,0,1,1,0,1,1, 0,1,0,1,0,1,0,1}; 
boolean trkUp[48] = {1,1,0,1,0,1,1,1, 1,1,0,1,1,0,1,1, 1,0,1,0,1,0,1,1, 1,0,1,1,1,0,1,1, 1,1,0,1,1,0,1,0, 1,1,0,1,0,1,0,1}; 
boolean trkDn[48] = {1,1,0,1,0,1,1,1, 1,1,0,1,1,0,1,1, 1,0,1,0,1,0,1,1, 0,1,0,1,1,1,0,1, 1,1,1,1,1,0,1,0, 1,1,0,1,0,1,0,1}; 
boolean power[48] = {1,1,0,1,0,1,1,1, 1,1,0,1,1,0,1,1, 1,0,1,0,1,0,1,1, 0,1,1,1,0,1,1,1, 1,1,1,0,1,0,1,1, 0,1,0,1,0,1,0,1}; 
boolean entPlay[48] = {1,1,0,1,0,1,1,1, 1,1,0,1,1,0,1,1, 1,0,1,0,1,0,1,1, 0,1,0,1,0,1,1,1, 1,1,1,1,1,1,0,1, 0,1,0,1,0,1,0,1}; 
boolean bandProg[48] = {1,1,0,1,0,1,1,1, 1,1,0,1,1,0,1,1, 1,0,1,0,1,0,1,1, 0,1,1,0,1,0,1,1, 1,1,1,1,0,1,1,1, 0,1,0,1,0,1,0,1}; 
boolean spFlag = 0; 
boolean dpFlag = 0; 
boolean hpFlag = 0; 
int button = 0;  
int spbutton = 0; 
/* 
0-none 
1-mode 
2-track + 
3-track - 
4-mute 
5-vol+ 
6-vol- 
*/ 
void setup() { 
Serial.begin(9600); 
pinMode(7, OUTPUT); 
} 
void loop() { 
static unsigned long oldTime = 0; 
int switchStatus = 0; 
if (millis() >= oldTime + CHECK_MS) { 
oldTime = millis(); 
switchStatus = CheckSwitch(); 
if (switchStatus == 0) { 
//no button press 
} else if (switchStatus == 1) { 
// single press 
switch (spbutton) { 
case 0: // no butto, why are wh here 
break; 
case 1: // mode 
modeSend(); 
break; 
case 2: // next up 
trkUpSend(); 
break; 
case 3: // next down 
trkDnSend(); 
break; 
case 4: // mute 
muteSend(); 
break; 
case 5: // vol up 
volUpSend(); 
break; 
case 6: // vol down 
volDnSend(); 
break; 
}  
} else if (switchStatus == 2) { 
//double press 
switch (spbutton) { 
case 0: // no butto, why are wh here 
break; 
case 1: // mode 
sourceSend(); 
break; 
case 2: // next up 
trkUpSend(); 
break; 
case 3: // next down 
trkDnSend(); 
break; 
case 4: // mute 
muteSend(); 
break; 
case 5: // vol up 
volUpSend(); 
break; 
case 6: // vol down 
volDnSend(); 
break; 
}  
} else if (switchStatus == 3) { 
//hold 
switch (spbutton) { 
case 0: // no butto, why are wh here 
break; 
case 1: // mode 
modeSend(); 
break; 
case 2: // next up 
trkUpSend(); 
break; 
case 3: // next down 
trkDnSend(); 
break; 
case 4: // mute 
muteSend(); 
break; 
case 5: // vol up 
volUpSend(); 
break; 
case 6: // vol down 
volDnSend(); 
break; 
}  
}  
} 
} 
// Service routine called by a timer interrupt 
int CheckSwitch() { 
static uint16_t State = 0; // Current debounce status 
static int curTime = 0; 
State=(State<<1) | !RawKeyPressed() | 0xe000; 
if (!spFlag) { 
if (hpFlag) { 
if (State == 0xe000) { 
return 3; 
} else { 
hpFlag = 0; 
} 
} 
if (State==0xf000) { 
spFlag = 1; 
hpFlag = 1; 
dpFlag = 1; 
curTime = 0; 
spbutton = button; 
return 0; 
} 
}  
if (hpFlag && State != 0xe000) { 
hpFlag = 0; 
} 
if (spFlag && hpFlag && curTime > HOLD_MS/CHECK_MS) { 
spFlag = 0; 
dpFlag = 0; 
return 3; 
} else if (spFlag && dpFlag && State == 0xf000 && curTime < DOUBLE_MS) { 
spFlag = 0; 
hpFlag = 0; 
dpFlag = 0; 
return 2; 
} else if (spFlag && !hpFlag && curTime > DOUBLE_MS) { 
spFlag = 0; 
hpFlag = 0; 
dpFlag = 0; 
return 1; 
} else { 
curTime = curTime + CHECK_MS; 
return 0; 
} 
} 
boolean RawKeyPressed() { 
int anaPin = 0; 
anaPin = analogRead(0); 
if (anaPin > NO_B - 20) { 
button = 0; 
return 0; 
} else if (anaPin > MODE_B - 20 && anaPin < MODE_B + 20 ) { 
button = 1; 
return 1; 
} else if (anaPin > NXTU_B - 20 && anaPin < NXTU_B + 20 ) { 
button = 2; 
return 1; 
} else if (anaPin > NXTD_B - 20 && anaPin < NXTD_B + 20 ) { 
button = 3; 
return 1; 
} else if (anaPin > MUTE_B - 20 && anaPin < MUTE_B + 20 ) { 
button = 4; 
return 1; 
} else if (anaPin > VOLU_B - 20 && anaPin < VOLU_B + 20 ) { 
button = 5; 
return 1; 
} else if (anaPin < VOLD_B + 20 ) { 
button = 6; 
return 1; 
} else { 
button = 0; 
return 0; 
} 
} 
//-----------SOURCE------------------ 
void sourceSend() { 
//first send 8ms high 
digitalWrite(alpPin, HIGH); 
delay(8); 
// send 4.5ms low 
digitalWrite(alpPin, LOW); 
delayMicroseconds(4500); 
for (int i = 0; i <= 47; i++) { 
//send bit for 0.5ms 
if (source[i] == 1 ) { 
digitalWrite(alpPin, HIGH); 
} else { 
digitalWrite(alpPin, LOW); 
}  
delayMicroseconds(500); 
// wait 0.5ms 
digitalWrite(alpPin, LOW); 
delayMicroseconds(500); 
} 
// send 41ms low 
digitalWrite(alpPin, LOW); 
delay(41);  
} 
//---------MODE----------------------------------------------- 
void modeSend() { 
//first send 8ms high 
digitalWrite(alpPin, HIGH); 
delay(8); 
// send 4.5ms low 
digitalWrite(alpPin, LOW); 
delayMicroseconds(4500); 
for (int i = 0; i <= 47; i++) { 
//send bit for 0.5ms 
if (entPlay[i] == 1 ) { 
digitalWrite(alpPin, HIGH); 
} else { 
digitalWrite(alpPin, LOW); 
}  
delayMicroseconds(500); 
// wait 0.5ms 
digitalWrite(alpPin, LOW); 
delayMicroseconds(500); 
} 
// send 41ms low 
digitalWrite(alpPin, LOW); 
delay(41);  
} 
//---------NEXT UP----------------------------------------------- 
void trkUpSend() { 
//first send 8ms high 
digitalWrite(alpPin, HIGH); 
delay(8); 
// send 4.5ms low 
digitalWrite(alpPin, LOW); 
delayMicroseconds(4500); 
for (int i = 0; i <= 47; i++) { 
//send bit for 0.5ms 
if (trkUp[i] == 1 ) { 
digitalWrite(alpPin, HIGH); 
} else { 
digitalWrite(alpPin, LOW); 
}  
delayMicroseconds(500); 
// wait 0.5ms 
digitalWrite(alpPin, LOW); 
delayMicroseconds(500); 
} 
// send 41ms low 
digitalWrite(alpPin, LOW); 
delay(41);  
} 
//---------NEXT DOWN---------------------------------------------- 
void trkDnSend() { 
//first send 8ms high 
digitalWrite(alpPin, HIGH); 
delay(8); 
// send 4.5ms low 
digitalWrite(alpPin, LOW); 
delayMicroseconds(4500); 
for (int i = 0; i <= 47; i++) { 
//send bit for 0.5ms 
if (trkDn[i] == 1 ) { 
digitalWrite(alpPin, HIGH); 
} else { 
digitalWrite(alpPin, LOW); 
}  
delayMicroseconds(500); 
// wait 0.5ms 
digitalWrite(alpPin, LOW); 
delayMicroseconds(500); 
} 
// send 41ms low 
digitalWrite(alpPin, LOW); 
delay(41);  
} 
//---------MUTE--------------------------------------------------- 
void muteSend() { 
//first send 8ms high 
digitalWrite(alpPin, HIGH); 
delay(8); 
// send 4.5ms low 
digitalWrite(alpPin, LOW); 
delayMicroseconds(4500); 
for (int i = 0; i <= 47; i++) { 
//send bit for 0.5ms 
if (mute[i] == 1 ) { 
digitalWrite(alpPin, HIGH); 
} else { 
digitalWrite(alpPin, LOW); 
}  
delayMicroseconds(500); 
// wait 0.5ms 
digitalWrite(alpPin, LOW); 
delayMicroseconds(500); 
} 
// send 41ms low 
digitalWrite(alpPin, LOW); 
delay(41);  
} 
//---------VOL UP----------------------------------------------- 
void volUpSend() { 
//first send 8ms high 
digitalWrite(alpPin, HIGH); 
delay(8); 
// send 4.5ms low 
digitalWrite(alpPin, LOW); 
delayMicroseconds(4500); 
for (int i = 0; i <= 47; i++) { 
//send bit for 0.5ms 
if (volUp[i] == 1 ) { 
digitalWrite(alpPin, HIGH); 
} else { 
digitalWrite(alpPin, LOW); 
}  
delayMicroseconds(500); 
// wait 0.5ms 
digitalWrite(alpPin, LOW); 
delayMicroseconds(500); 
} 
// send 41ms low 
digitalWrite(alpPin, LOW); 
delay(41);  
} 
//---------VOL DOWN----------------------------------------------- 
void volDnSend() { 
//first send 8ms high 
digitalWrite(alpPin, HIGH); 
delay(8); 
// send 4.5ms low 
digitalWrite(alpPin, LOW); 
delayMicroseconds(4500); 
for (int i = 0; i <= 47; i++) { 
//send bit for 0.5ms 
if (volDn[i] == 1 ) { 
digitalWrite(alpPin, HIGH); 
} else { 
digitalWrite(alpPin, LOW); 
}  
delayMicroseconds(500); 
// wait 0.5ms 
digitalWrite(alpPin, LOW); 
delayMicroseconds(500); 
} 
// send 41ms low 
digitalWrite(alpPin, LOW); 
delay(41);  
} 
 Пытаюсь разобраться, читаю вторые сутки инфу по сабжу, но пока пробелов в понимании процесса слишком много.