appicals auf dem Arduino

Auf dieser Seite wird ein Minimalbeispiel vorgestellt, welches das Zusammenspiel zwischen Diensten, der SixML und dem CommFramework zeigt. Für das Nachstellen benötigt man einen aktuellen Arduino sowie die Arduino-Entwicklungsumgebung. Der vollständige Sketch hierzu kann ebenfalls heruntergeladen werden.

Arduino mit RelativeInput-Dienst

Im Folgenden wollen wir das Szenario durchspielen, bei dem ein Potentiometer an den analogen Eingang eines Arduino angeschloßen ist. Diese Konstellation könnte z.B. Teil eines größeren Mischpultes sein oder als Regler für eine dimmbare Lampe dienen.

Abb.: Arduino mit Potentiometer am analogen Eingang

Um das Beispiel simpel zu halten, wird der Arduino über seine serielle Schnittstelle mit einem PC verbunden. Hierbei bietet der Arduino über appicals dem PC einen RelativeInput-Dienst an, welcher die Werte des am analogen Eingang angebundenen Potentiometer ausliest.

Des Weiteren wird dem Arduino die GeräteID 222 zugewiesen.

Dieses Beispiel wurde im folgenden Code für den Arduino umgesetzt. Der Code wurde so ausgelegt, dass der Arduino den Potentiometer an dessen analogen Eingang 0 vermutet.

/**************************************************************
 * appicals example for Arduino
 * - Potentiometer connected to analog pin:
 * - Center pin of the potentiometer goes to the analog pin 0.
 * - Side pins of the potentiometer go to +5V and ground
 *
 * created  17 Jul 2014
 * modified 01 Aug 2014
 * by Gerrit Eberle
 **************************************************************/
/*********************
 * GLOBAL PARAMETERS *
 *********************/
int i_message[512];
int i_mCounter = 0;

int i_magicNumber[] = {4, 193, 29, 183};
int i_magic = 0;

int i_byte = 0; // one byte of the stream

int i_payloadSize = 0;
int i_pCounter = 0;

bool b_messageStart = false;
bool b_headerFinished = false;
bool b_payloadSize = false;

// time counter
int i_ten_min = 0; // 10min = 300000 * 2ms(delay)
int i_sendID = 0; // Counter for the sending messages
int i_receiveID = 0; // Counter for the receiving messages

// parameters of the connected hardware
const int analogIn_Poti = A0;
int sensorValue_Poti = 0;  // value of the Potentiometer
int sensorValue_PotiTmp  = 0; // temporary storage of the value of the Potentiometer


/******************
 * HELP FUNCTIONS *
 ******************/
// Reset Message and its parameter to be ready for the next message.
void resetMessage(){
  for(i_mCounter = 0; i_mCounter < 32; i_mCounter++){
    i_message[i_mCounter] = 0;
  }
  i_mCounter = 0;
  i_magic = 0;
  i_payloadSize = 0;
  i_pCounter = 0;
  b_messageStart = false;
  b_headerFinished = false;
  b_payloadSize = false;
}

// print received message back to PC (bytes are interpreted as ASCII characters)
void printMessage(){
  int i = 0;
  for(i = 0; i < i_mCounter; i++){
    Serial.print(i_message[i]);
    Serial.print(" (");
    Serial.print(i);
    Serial.print("),");
  }
  Serial.print(" - MessageSize: ");
  Serial.println(i_mCounter);
}

// Checking for Magic Number
bool checkMagicNumber(int i_byte){
  bool b_found = false;
  if(i_magic > 3){
    i_magic = 0;
  } 
  else {
    if(i_byte == i_magicNumber[i_magic]){
      if(i_magic == 3){
        b_found = true;
      } 
      else {
        i_magic++;
      }
    }
  }
  return b_found;
}


/**********************************
 * HARDWARE INTERACTION FUNCTIONS *
 **********************************/
// Potentiometer
// return: 0..1023
int getPotentioValue(){
  int i_return = analogRead(analogIn_Poti);
  return i_return;
}


/*****************************
 * APPICALS SENDING MESSAGES *
 *****************************/
// Serializer header
void subsendHeader(int i_protocolID, int i_contentSize){
  int i = 0;
  for(i = 0; i < 4; i++){
    Serial.write(i_magicNumber[i]);
  }
  i_sendID++;
  Serial.write(i_sendID);
  Serial.write(i_protocolID);
  // Max. i_contentSize = 65535 (cause: only 2 Bytes for value of size.)
  Serial.write(highByte(i_contentSize));
  Serial.write(lowByte(i_contentSize));
}

// STRAP (ProtocolID = 40)
void subsendSTRAPPart(){
  Serial.write(1);
  Serial.write(21);
  Serial.write(20);
}

void sendMessage(int i_messageContent[], int i_messageContentSize){
  int i = 0;

  subsendHeader(40, i_messageContentSize + 3); // Protocol ID of STRAP: 40, bytes after serializer header : 24 (3 bytes STRAP, 21 bytes rest message content)
  subsendSTRAPPart(); // 3 Bytes (The rest of the message can only have a size of 21 bytes.)

  // Rest of the message:
  // Example: 21,01,01,02,02,01,00,42,01,222,41,05,07,221,11,14,00,46,01,31,00
  for(i = 0; i < i_messageContentSize; i++){
    Serial.write(i_messageContent[i]);
  }
}

void sendMsg_DiscoveryInformation(){
  int i_discoveryContentSize = 21;
  int i_discoveryContent[] = {21,01,01,02,02,01,00,42,01,222,41,05,07,221,11,14,00,46,01,31,00};
  sendMessage(i_discoveryContent, i_discoveryContentSize);
}

void sendMsg_DiscoveryResponse(){
  int i_discoveryContentSize = 21;
  int i_discoveryContent[] = {23,01,01,02,02,01,00,42,01,222,41,05,07,221,11,14,00,46,01,31,00};
  sendMessage(i_discoveryContent, i_discoveryContentSize);
}

void sendMsg_DescriptionResponse(){
  int i_descriptionContentSize = 47;
  int i_descriptionContent[] = {25,02,20,01,42,01,222,43,02,00,30,44,07,65,114,100,117,105,110,111,48,03,03,00,00,49,02,02,88,70,15,72,01,31,73,01,31,79,02,12,32,75,03,16,00,00,00};
  sendMessage(i_descriptionContent, i_descriptionContentSize);
}

void sendMsg_DescriptionResponse_Service(int i_serviceID){
  if(i_serviceID == 31){ // ServiceDesciption of Service 31
    int i_descriptionContentSize = 28;
    int i_descriptionContent[] = {25,2,21,1, 70,21, 72,1,31, 79,2,12,28, 75,3,16,0,0, 33,1,3, 35,4,70,0,20,1, 0};
    sendMessage(i_descriptionContent, i_descriptionContentSize);
  }
}

void sendMsg_ControlResponse(int i_serviceID){
  int i_potiVal = getPotentioValue();
  int i_controlContentSize = 15;
  int i_controlContent[] = {27,2,33,1, 42,1,222, 72,1,31, 76,2,highByte(i_potiVal),lowByte(i_potiVal), 0};
  sendMessage(i_controlContent, i_controlContentSize);
}

void sendMsg_EventInformation(){
  int i_potiVal = getPotentioValue();
  int i_controlContentSize = 14;
  int i_controlContent[] = {28,1,33, 42,1,222, 72,1,31, 76,2,highByte(i_potiVal),lowByte(i_potiVal), 0};
  sendMessage(i_controlContent, i_controlContentSize);
}


/*************************************************
 * APPICALS RECEIVED MESSAGES AND THEIR ANALYSIS *
 *************************************************/
// Type of Message: Discovery Request (22)
int processMsg_Discovery(int i_contentStart, int i_contentSize){ // i_countStart-1: Type of Message
  int i_expectedMsg[] = {22,01,03,02,02,01,00,00};
  int i_expectedMsgSize = 8;
  int i_c = 0;

  if(i_expectedMsgSize == i_contentSize - i_contentStart){
    for(i_c = 0; i_c < i_expectedMsgSize; i_c++){
      if(i_expectedMsg[i_c] != i_message[i_c + i_contentStart]){
        return 0;
      }
    }
    sendMsg_DiscoveryResponse();
    return 1;
  } 
  else {
    return 0;
  }
}

// Type of Message: Description Request (24) - for Device, Services, ...
int processMsg_Description(int i_contentStart, int i_contentSize){
  int i_expectedMsg[] = {24,1,20,42,1,222,0};
  int i_expectedMsgSize = 7;
  int i_expMsg_Serv[] = {24,1,21,42,1,222,72,1,0,0}; // template of an expected description message for services
  int i_expMsgSize_Service = 10;
  int i_expMsgPosID_Service = 0;
  int i_message_tmp = 0;
  int i_ServiceID = 0;
  int i_c = 0;

  if(i_expectedMsgSize == i_contentSize - i_contentStart){
    for(i_c = 0; i_c < i_expectedMsgSize; i_c++){
      i_message_tmp = i_message[i_c + i_contentStart];
      if(i_expectedMsg[i_c] != i_message_tmp){
        return 0;
      }
    }
    sendMsg_DescriptionResponse();
    return 1;
  } else if(i_expMsgSize_Service == i_contentSize - i_contentStart){
    i_expMsgPosID_Service = i_expMsgSize_Service - 2;
    for(i_c = 0; i_c < i_expMsgSize_Service; i_c++){
      i_message_tmp = i_message[i_c + i_contentStart];
      if(i_c == i_expMsgPosID_Service){ // At position i_expMsgSize_Service - 2 we expect the ServiceID.
        i_ServiceID = i_message_tmp;
      } else if(i_expMsg_Serv[i_c] != i_message_tmp){
        return 0;
      }
    }
    sendMsg_DescriptionResponse_Service(i_ServiceID);
    return 1;
  } else {
    return 0;
  }
}

// Type of Message: Control Request (26) // Under construction
int processMsg_Control(int i_contentStart, int i_contentSize){
  int i_expectedMsg[] = {26,1,33,42,1,222,72,1,31,0};
  int i_expectedMsgSize = 10; 
  int i_c = 0;

  if(i_expectedMsgSize == i_contentSize - i_contentStart){
    for(i_c = 0; i_c < i_expectedMsgSize; i_c++){
      if(i_expectedMsg[i_c] != i_message[i_c + i_contentStart]){
        return 0;
      }
    }
    sendMsg_ControlResponse(31);
    return 1;
  } 
  else {
    return 0;
  }
}

// func: checkReceivedMsgContent
// description: This function parses the content of the message.
// info: Message Content = Message (x Byte) with x := i_contentSize
void checkReceivedMsgContent(int i_contentSize){
  int i_max = i_contentSize + 11; // in previous functions the contentSize value was reduced by 11. (8 Bytes Serializer, 3 Bytes STRAP)
  int i_processMsgSuccessful = 0;

  // Check Type of Message
  if(i_message[11] == 22){ // The content of the message starts at array position 11. The previous bytes contains only the serializer header and the STRAP header.
    i_processMsgSuccessful = processMsg_Discovery(11, i_max);
  } 
  else if(i_message[11] == 24){
    i_processMsgSuccessful = processMsg_Description(11, i_max);
  } 
  else if(i_message[11] == 26){
    i_processMsgSuccessful = processMsg_Control(11, i_max);
  } 
  else {
  }
}

// func: checkReceivedSTRAPMsg
// description: This function parses the STRAP message after the serializer header. The parsing of the message content will be processed in a sub function.
// info: STRAP Message = STRAP (3 Byte) + Message (x Byte) with x := i_msgSize Byte - 3 Byte
void checkReceivedSTRAPMsg(int i_msgSize){
  int i_contentSize = 0;

  if(i_msgSize > 0){
    //Serial.print("STRAP Message received (");
    //Serial.print(i_message[8]);
    //Serial.print(i_message[9]);
    //Serial.print(i_message[10]);
    i_contentSize = i_msgSize - 3; // Size of Message without Serializer Header reduced by the size of STRAP Header (3)
    if(i_contentSize > 0){
      checkReceivedMsgContent(i_contentSize);
    }
  }
}

// func: checkReceivedMessage
// description: This function parses the first 8 bytes of the message (Serializer header) and process the rest of the message according to this information.
// info: Message = Serializer (8 Byte) + STRAP (3 Byte) + Message (x Byte)
void checkReceivedMessage(){
  int i_checkID = 0;
  int i_checkProtocol = 0;
  int i_checkSize = 0;

  i_checkID = i_message[4]; // Can be used for analysis of the correct message order.
  i_checkProtocol = i_message[5];
  i_checkSize = i_message[7] + i_message[6] * 256; // Size of Message without Serializer Header.

  if(i_checkProtocol == 40){
    checkReceivedSTRAPMsg(i_checkSize);
  } 
  else {
    Serial.println("Arduino can not handle the message:");
    printMessage();
  }
}


/*************
 * MAIN PART *
 *************/
// initializing
void setup(){
  // initialize serial communications at 9600 bps:
  //  resetBuffer();
  resetMessage();
  sensorValue_Poti = getPotentioValue();
  Serial.begin(9600);
}

// application
void loop(){
  // read analog value of the potentiometer
  if(Serial.available() > 0){
    i_byte = Serial.read();
    // Serial.write(i_byte); // for DEBUG
    if(!b_messageStart){
      b_messageStart = checkMagicNumber(i_byte);
      if(b_messageStart){
        i_message[0] = i_magicNumber[0];
        i_message[1] = i_magicNumber[1];
        i_message[2] = i_magicNumber[2];
        i_message[3] = i_magicNumber[3];
        i_mCounter = 4; // 4 to get i_message[4] in the next loop.
      }
    } 
    else {
      // Checking the rest of the message to get the Header-Information
      if(!b_headerFinished){
        if(i_mCounter == 4){ // Message counter at position 5 of the message.
          i_message[4] = i_byte;
          // If you want you can check if the current message has the expected message counter.
          // For example: The previous message could get lost. So the message counter is higher than expected.
        } 
        else if(i_mCounter == 5){ // Protcol ID of the used transport protocol at position 6 of the message.
          i_message[5] = i_byte;
        } 
        else if(i_mCounter == 6){ // 1st part of the payload size
          i_message[6] = i_byte;
        } 
        else if(i_mCounter == 7){ // 2nd part of the payload size
          i_message[7] = i_byte;
          i_payloadSize = i_byte + i_message[6] * 256; // ATTENTION: Here we are directly using the received byte. Be careful if you are using the Arduino Monitor. This monitor will interpret the input value as an ASCII-Charakter and not as a byte.
          b_payloadSize = true;
          if(i_payloadSize == 0){ // If payload size is 0, the current message is only a ping message without any content.
            Serial.print("Ping -> Pong: ");
          } 
          else {
            b_headerFinished = true;
          }
        }
      } 
      else {
        i_message[i_mCounter] = i_byte;
        i_payloadSize--;
      }
      i_mCounter++;
      if(b_payloadSize && i_payloadSize == 0){ // END of Message reached.
        // printMessage(); // for DEBUG
        checkReceivedMessage();
        resetMessage();
      }
    }
  }
  
  // Send Discorvery Information if 10 minutes passed since the last sending of the Discovery Information.
  if(i_ten_min == 0){
    i_ten_min = 3000000; // ? 30 * 1000 ms * 10 == 10 min ?
    sendMsg_DiscoveryInformation();
  }
  
  // Send Event Information if value of potentiometer changed.
  sensorValue_PotiTmp = getPotentioValue();
  if(sensorValue_PotiTmp > (sensorValue_Poti + 2) || sensorValue_PotiTmp < (sensorValue_Poti - 2)){
    // The if check considers the error in measurement (here: +-2).
    sensorValue_Poti = sensorValue_PotiTmp;
    sendMsg_EventInformation();
    bad = true;
    Serial.print("Hello there");
  }

  delay(2);
  i_ten_min--;
}
	

Bekanntmachung des Gerätes

Um das Gerät gegenüber dem PC bekannt zu machen, sendet der Arduino alle 10 Minuten das folgende ByteArray über die serielle Schnittstelle:

		4,193,29,183,x,40,0,24, 1,21,20, 21,1,1, 2,2,1,0, 42,1,222, 41,5,7,221,11,14,0, 46,1,31, 0
	
4,193,29,183,x,40,0,24, ist der Serializer-Header:
  • Die ersten 4 Zahlen stellen die 4 Byte große Magic number von appicals dar.
  • x wird mit jedem gesendeten Paket durch den Arduino um 1 erhöht.
  • Da für die serielle Schnittstelle kein Netzwerkprotokoll benötigt wird (DirectNetwork), fehlt der Netzwerk-Header und das Serializer-Protokoll verweist direkt auf STRAP (ProtocolID 40).
  • 0,24 ist die 2 Byte große Gesamtgröße von STRAP-Header und SixML-Nachricht (High Byte ist 0, Low Byte ist 24).
1,21,20, ist der STRAP-Header:
  • Dieser gibt an der ersten Stelle GenericApp (ProtocolID 1) als ApplicationProtocolID an.
  • Als Quell- und Zielport werden Port 21 und Port 20 verwendet.
21,1,1, 2,2,1,0, 42,1,222, 41,5,7,221,11,14,0, 46,1,31, 0 ist die SixML-Nachricht vom Typ DeviceAnnouncement. Sie besteht aus den unter SixML-Discovery beschriebenen Tupeln:
  • DiscoveryInformation.DeviceAnnouncement (21,1,1)
  • SDLVersion (2) mit der Version 1.0 (1,0)
  • DeviceID (42) mit der ID 222 (222)
  • DeviceDescriptionDate (41): 7,221,11,14,0 entspricht 2014-11-14.
  • ServiceTypeList (46) mit einem RelativeInput-Dienst (31)

Suche durch den PC

Der PC sendet z.B. folgendes ByteArray über die serielle Schnittstelle um alle Geräte zu finden.

		4,193,29,183,y,40,0,11, 1,21,20, 22,1,3, 2,2,1,0, 0
	
4,193,29,183,y,40,0,11, ist der Serializer-Header:
  • Die ersten 4 Zahlen stellen die 4 Byte große Magic number von appicals dar.
  • y wird mit jedem gesendeten Paket durch den PC um 1 erhöht.
  • Da für die serielle Schnittstelle kein Netzwerkprotokoll benötigt wird (DirectNetwork), fehlt der Netzwerk-Header und das Serializer-Protokoll verweist direkt auf STRAP (ProtocolID 40).
  • 0,11 ist die 2 Byte große Gesamtgröße von STRAP-Header und SixML-Nachricht (High Byte ist 0, Low Byte ist 11).
1,21,20, ist der STRAP-Header:
  • Dieser gibt an der ersten Stelle GenericApp (ProtocolID 1) als ApplicationProtocolID an.
  • Als Quell- und Zielport werden Port 21 und Port 20 verwendet.
22,1,3, 2,2,1,0, 0 ist die SixML-Nachricht vom Typ DeviceSearch. Sie besteht aus den unter SixML-Discovery beschriebenen Tupeln:
  • DiscoveryRequest.DeviceSearch (22,1,3)
  • SDLVersion (2) mit der Version 1.0 (1,0)

Hierauf erhält der PC vom Arduino über die serielle Schnittstelle die passende Rückantwort.

		4,193,29,183,x,40,0,24, 1,21,20, 23,1,1, 2,2,1,0, 42,1,222, 41,5,7,221,11,14,0, 46,1,31, 0
	

Der einzige Unterschied zur DiscoveryInformation (21) liegt darin, dass es sich hier um eine DiscoveryResponse (23) auf eine DiscoveryRequest handelt.

Gerätebeschreibungsabruf durch den PC

Der PC wird anschließend versuchen, die Gerätebeschreibung abzurufen. Dazu sendet er folgendes ByteArray über die serielle Schnittstelle.

		4,193,29,183,y,40,0,10, 1,21,20, 24,1,20, 42,1,222, 0
	
4,193,29,183,y,40,0,10, ist der Serializer-Header:
  • Die ersten 4 Zahlen stellen die 4 Byte große Magic number von appicals dar.
  • y wird mit jedem gesendeten Paket durch den PC um 1 erhöht.
  • Da für die serielle Schnittstelle kein Netzwerkprotokoll benötigt wird (DirectNetwork), fehlt der Netzwerk-Header und das Serializer-Protokoll verweist direkt auf STRAP (ProtocolID 40).
  • 0,10 ist die 2 Byte große Gesamtgröße von STRAP-Header und SixML-Nachricht (High Byte ist 0, Low Byte ist 10).
1,21,20, ist der STRAP-Header:
  • Dieser gibt an der ersten Stelle GenericApp (ProtocolID 1) als ApplicationProtocolID an.
  • Als Quell- und Zielport werden Port 21 und Port 20 verwendet.
24,1,20, 42,1,222, 0 ist die SixML-Nachricht vom Typ DeviceSearch. Sie besteht aus den unter SixML-Discovery beschriebenen Tupeln:
  • DescriptionRequest.DeviceDescription (24,1,20)
  • DeviceID (42) mit der ID 222 (222)

Der Arduino parst die Nachricht und sendet anschließend seine Gerätebeschreibung.

		4,193,29,183,x,40,0,50, 1,21,20, 25,2,20,1, 42,1,222, 43,2,0,30, 44,7,65,114,100,117,105,110,111,
48,3,3,0,0, 49,2,2,88, 70,15, 72,1,31, 73,1,31, 79,2,12,32, 75,3,16,0,0, 0
4,193,29,183,x,40,0,50, ist der Serializer-Header:
  • Die ersten 4 Zahlen stellen die 4 Byte große Magic number von appicals dar.
  • x wird mit jedem gesendeten Paket durch den Arduino um 1 erhöht.
  • Da für die serielle Schnittstelle kein Netzwerkprotokoll benötigt wird (DirectNetwork), fehlt der Netzwerk-Header und das Serializer-Protokoll verweist direkt auf STRAP (ProtocolID 40).
  • 0,50 ist die 2 Byte große Gesamtgröße von STRAP-Header und SixML-Nachricht (High Byte ist 0, Low Byte ist 50).
1,21,20, ist der STRAP-Header:
  • Dieser gibt an der ersten Stelle GenericApp (ProtocolID 1) als ApplicationProtocolID an.
  • Als Quell- und Zielport werden Port 21 und Port 20 verwendet.
25,2,20,1, 42,1,222, 43,2,0,30, 44,7,65,114,100,117,105,110,111, 48,3,3,0,0, 49,2,2,88, 70,15, 72,1,31, 73,1,31, 79,2,12,32, 75,3,16,0,0, 0 ist die SixML-Nachricht vom Typ DeviceSearch. Sie besteht aus den unter SixML-Discovery beschriebenen Tupeln:
  • DescriptionResponse.DeviceDescription (25,2,20) mit dem Result: OK (1)
  • DeviceID (42) mit der ID 222 (222)
  • DeviceExpectedLifeTime (43) von 30min (0,30)
  • DeviceName (44): Arduino (65,114,100,117,105,110,111)
  • DeviceLocation (48): Floor (3) 0 0
  • DeviceDescriptionTag (49): Sensor (2,88)
  • ServiceDescriptionContainer (70) mit einer Größe von 15 Bytes:
    • ServiceID (72): 31
    • ServiceType (73): RelativeInput (31)
    • ServiceDescriptionTag (79): RelativePotentiometer (12,32)
    • ServiceFlags(75): 16,0,0 => Implementation:Basic;SuppCtrlRequests:0x01;Version:1.0 (k.A. wie sich das aus den Zahlen davor ergibt!)
Die XML-Repräsentation der in der SixML-Nachricht enthaltenen DeviceDescription sähe wie folgt aus:
<DescriptionResponse class="DeviceDescription" result="Ok" >
  <DeviceID>222</DeviceID>
  <DeviceExpectedLifeTime HexValue="0x00-1E" >30</DeviceExpectedLifeTime>
  <DeviceName>Arduino</DeviceName>
  <DeviceLocation>DiningRoom</DeviceLocation>
  <DeviceDescriptionTag>Sensor</DeviceDescriptionTag>
  <ServiceDescriptionContainer>
    <ServiceID>31</ServiceID>
    <ServiceType>RelativeInput</ServiceType>
    <ServiceDescriptionTag>Potentiometer</ServiceDescriptionTag>
    <ServiceFlags Implementation="Basic" SuppCtrlRequests="0x00" Version="1.0" />
  </ServiceDescriptionContainer>
</DescriptionResponse>
	

Ereignis-Nachrichten

Stellt der Arduino eine Änderung an seinem analogen Eingang fest, dann sendet er eine Event-Nachricht als folgendes ByteArray über die serielle Schnittstelle.

		4,193,29,183,x,40,0,17, 1,21,20, 28,1,33, 42,1,222, 72,1,31, 76,2,1,244, 0
	
4,193,29,183,x,40,0,17, ist der Serializer-Header:
  • Die ersten 4 Zahlen stellen die 4 Byte große Magic number von appicals dar.
  • x wird mit jedem gesendeten Paket durch den Arduino um 1 erhöht.
  • Da für die serielle Schnittstelle kein Netzwerkprotokoll benötigt wird (DirectNetwork), fehlt der Netzwerk-Header und das Serializer-Protokoll verweist direkt auf STRAP (ProtocolID 40).
  • 0,17 ist die 2 Byte große Gesamtgröße von STRAP-Header und SixML-Nachricht (High Byte ist 0, Low Byte ist 17).
1,21,20, ist der STRAP-Header:
  • Dieser gibt an der ersten Stelle GenericApp (ProtocolID 1) als ApplicationProtocolID an.
  • Als Quell- und Zielport werden Port 21 und Port 20 verwendet.
28,1,33, 42,1,222, 72,1,31, 76,2,1,244, 0 ist die SixML-Nachricht vom Typ DeviceSearch. Sie besteht aus den unter SixML-Discovery beschriebenen Tupeln:
  • MessageEventInformation.ServiceValue (28,1,33)
  • DeviceID (42) mit der ID 222 (222)
  • ServiceID (72): 31
  • ServiceValue (76): 1,244 (1*256 + 244 = 500)
Anmerkungen zur Umsetzung dieses Szenarios mit dem Arduino

Für jene, die noch wenig Erfahrung mit dem Arduino haben, ist es erst einmal wichtig zu wissen, wie der Arduino genau "tickt":

Auf dem Arduino wird zur Laufzeit ein Thread erzeugt, der bis zu dessen Ausschalten immer wieder vom Arduino aufgerufen wird. Um diesen Thread bei Anschalten des Arduinos zu initialisieren, bietet der Arduino eine Initialisierungsfunktion an.
Diese Funktionen für den Thread sind dabei wie folgt benannt:

appicals in the loop

Die loop-Schleife muss sich um 2 appicals-Aufgaben kümmern: