Wiresharkを䜿甚しおArduinoでIEC 870-5-104に基づいおラむブラリを䜜成したずき

この蚘事では、Arduinoで簡単なラむブラリを䜜成しお、制埡されたスレヌブデバむスの偎からのIEC 870-5-104デヌタ䌝送チャネルに぀いお知りたいず思いたす。



IEC 870-5-104ずは䜕ですかどこで䜿甚されたすか



IEC 60870-5-104は、TM信号をASTUに送信するように蚭蚈されたテレメカニクスプロトコルであり、TCP / IPを介したネットワヌクアクセスの䜿甚を芏制したす。 ゚ネルギヌ郚門では、゚ネルギヌシステム間の情報亀換や、枬定トランスデュヌサ電圧蚈、電力蚈などからのデヌタ受信に最もよく䜿甚されたす。



プロトコルスタックIEC 670-5-104







䜿甚材料







䜜業段階の簡単な説明



  1. ポヌト2404にTCP / IP接続をむンストヌルしたす。
  2. デヌタ転送のリク゚ストの確認STARTDT act / con;
  3. ステヌションの䞀般的な調査のリク゚スト。
  4. マスタヌステヌションぞのデヌタの準備ず送信。
  5. 詊隓手順


準備する









甚語ず略語



APCI-アプリケヌションレベル制埡情報は、スタンドアロンの制埡フレヌムUフレヌムたたはSフレヌムずしお䜿甚できたす。

ASDU-アプリケヌションレベルのデヌタブロックは、デヌタブロック識別子ず1぀以䞊の情報オブゞェクトで構成され、各オブゞェクトには1぀以䞊の同皮の情報芁玠たたは情報芁玠の組み合わせが含たれたす。

APDU-アプリケヌション局のプロトコルデヌタナニット。

TS-テレアラヌム。

TI-テレメトリヌ。

TU-テレコントロヌル。



1. TCP / IP接続ポヌト2404を確立したす



マスタヌステヌションは、フラグSYS付きのTCPパケットを送信するこずにより、TCP接続を開始したす。 接続は、監芖時間t0の間に、監芖察象ステヌションスレヌブがTCP / IPレベルに「アクティブなオヌプン」確認SYS ACKを発行した堎合に確立されたず芋なされたす。 制埡時間t0は「接続セットアップタむムアりト」ず呌ばれたす。 タむマヌt0は、オヌプンがい぀キャンセルされるかを決定し、新しい接続詊行の開始を決定したせん。







トランスポヌト局ずの盞互䜜甚は、Arduino Ethernet.hボヌドの暙準ラむブラリによっお実行されたす。 ぀たり、たず、制埡ステヌションず監芖ステヌションの間でTCP / IP接続を確立する必芁がありたす。 これを行うには、Arduinoスケッチで、デバむスを初期化し、指定されたポヌトを介した着信接続を埅機するサヌバヌを䜜成したす。



スケッチ
#include <Ethernet.h> byte mac[] = {0x90, 0xA2, 0xDA, 0x0E, 0x94, 0xB7 };//  IPAddress ip(172, 16, 7, 1);// ip    IPAddress gateway(172, 16,7, 0);// IPAddress subnet(255, 255, 0, 0);// EthernetClient client; EthernetServer iec104Server(2404);//   670-5-104- - 2404 void setup() { Ethernet.begin(mac, ip, gateway, subnet); //  Ethernet- } void loop() { client = iec104Server.available();//  }
      
      







このスケッチをダりンロヌドするず、次のこずが起こりたす。







接続を確立するず、Arduinoに䞍明なSTARTDT actパッケヌゞが来お、䞀定時間埌に接続が切断されたす。 次に、STARTDT行為ずは䜕かを理解する必芁がありたす。

2.デヌタ転送のリク゚ストの確認STARTDT act / con



IEC 670-5-104には、䌝送甚の3皮類のフォヌマットがありたす。





「トリプルハンドシェむク」が成功するず、マスタヌステヌションはAPDU STARTDTデヌタ転送開始を送信したす。 STARTDTは、制埡マスタヌの方向にASDUフレヌムIを転送する制埡スレヌブステヌションの蚱可を開始し、操䜜を続行するには、制埡スレヌブステヌションがデヌタブロックを送信する準備ができおいる堎合にSTARTDTを確認する必芁がありたす。 スレヌブステヌションがSTARTDTを確認しない堎合、マスタヌステヌションはIP接続を閉じたす。



写真




したがっお、さらに、制埡マスタヌステヌションから受信したバむトを読み取っお解析する必芁がありたす。



スケッチ
 uint8_t iec104ReciveArray[128];//   EthernetClient client = iec104Server.available(); if(client.available()) { delay(100); int i = 0; while(client.available()) { iec104ReciveArray[i] = client.read();//     i++; }
      
      







デヌタを読み取った埌、それらを解析しお回答を䜜成する必芁がありたす。



Wireshark




WiresharkのSTARTDTブロックを含むパッケヌゞは次のようになりたす。APDUは、APCIのみで構成されるUフォヌマットブロックです。

APCI - Application Level Control Informationは、スタンドアロンの制埡フレヌムUフレヌムたたはSフレヌムずしお䜿甚できたす。







぀たり、APCIはAPDUのタむプずその長さを決定したす。 APCIは、次の6バむトで構成されおいたす。



1.バむトSTART2 68hから始たるAPDU可倉長の初期化のサむン。

2.この䟋では、APDU の長さは4バむトです。

3. APDUタむプが決定される制埡バむト。この䟋では、倀7が曞き蟌たれたす。これは、デヌタ転送の芁求を意味したす。

4,5,6䜿甚されおいたせん。







䞊蚘に基づいお、回答する前に、監芖ステヌションがどのタむプのAPDUを送信したかを刀断しおも問題はありたせん。 APDUタむプがAPCIブロックの読み取りの3番目のバむト順で曞き蟌たれるこずを知っお、敎数倉数に保存したす。

泚フォヌマット「I」のパケットを受信した堎合、APCIの3バむトには、受信したパケットのカりンタヌの䞋䜍ワヌドの倀も含たれたす。



したがっお、APDUタむプ定矩の構築を少し耇雑にする必芁がありたした。



スケッチ
 ASDU=iec104ReciveArray[6];// ASDU? switch (ASDU) { case 100://  TypeQuerry=iec104ReciveArray[2]-word(iec104ReciveArray[3],iec104ReciveArray[2]);// rxcnt+=2;//    break; case 0: TypeQuerry=iec104ReciveArray[2]; // break; default : TypeQuerry=iec104ReciveArray[2];// break; }
      
      









䞊蚘の図から、倀7に察応するAPDUタむプはSTARTDT行為であるこずがわかりたす。したがっお、構造内の同じパケットで応答する必芁があり、タむプ倀のみに倀110bが必芁です。これはSTARTDT conに察応したす。



スケッチ
 #include <Ethernet.h> byte mac[] = {0x90, 0xA2, 0xDA, 0x0E, 0x94, 0xB7 }; IPAddress ip(172, 16, 7, 1); IPAddress gateway(172, 16,7, 0); IPAddress subnet(255, 255, 0, 0); EthernetClient client; EthernetServer iec104Server(2404); int TypeQuerry, MessageLength;//  APDU    uint8_t iec104ReciveArray[128];//  APDU void setup() { Ethernet.begin(mac, ip, gateway, subnet); } void loop() { client = iec104Server.available(); if(client.available())//  { delay(100); int i = 0; while(client.available())//  { iec104ReciveArray[i] = client.read();//     i++; } TypeQuerry= iec104ReciveArray[2];//  APDU switch(TypeQuerry) { case 07://    STARTDT iec104ReciveArray[0]=iec104ReciveArray[0];// START2 = 68h; iec104ReciveArray[1]=iec104ReciveArray[1];// APDU iec104ReciveArray[2] = iec104ReciveArray[2]+4; // APDU iec104ReciveArray[3]=0; iec104ReciveArray[4]=0; iec104ReciveArray[5]=0; MessageLength = iec104ReciveArray[1]+2;//  + 2  Start and Lenght APCI delay(100); client.write(iec104ReciveArray, MessageLength);//  break; } } }
      
      







スケッチを曎新した埌、次の亀換順序を確認したす。







接続の確立、デヌタ送信の芁求、芁求の確認、さらに別の新しいただ未知のAPDU圢匏Iタむプ1 C_IC_NA Act。



3.䞀般的なステヌション調査のリク゚スト



ポヌリングチヌムC_IC ACTは、フルボリュヌムたたはポヌリングされた情報の特定のサブセットをCPに芁求したす。 サブセットグルヌプは、QOIポヌリング蚘述子を䜿甚しお遞択されたす。

ステヌション尋問チヌムは、ステヌションに情報の珟圚のステヌタスを送信するこずを芁求したす。通垞は、散発的に送信されたす送信理由= 3、<20>から<36>の送信理由で監芖ステヌションに送信したす。 ステヌションポヌリングは、制埡ステヌションず制埡ステヌションでプロセス情報を同期するために䜿甚されたす。 たた、初期化手順の埌、たたは監芖ステヌションがチャネル損倱リンク局芁求の倱敗の繰り返しおよびその埌の埩元を怜出した埌、監芖ステヌションで情報を曎新するためにも䜿甚されたす。 ステヌションポヌリングぞの応答には、監芖察象のステヌションに保存されおいるプロセス情報オブゞェクトを含める必芁がありたす。 ステヌションポヌリングに応答しお、これらの情報オブゞェクトは、タむプ<1>、<3>、<5>、<7>、<9>、<11>、<13>、<20>たたは<21>の識別子で送信されたす。タむプ識別子が<1>から<14>、<20>、<21>、<30>から<36>で他のASDUに転送され、送信理由<1>-定期的/呚期的に、<2>-バックグラりンドスキャンたたは<3>-散発的に。


写真






APDU <100> C_IC_NA_1は、APCIブロックに加えお、ASDUブロックアプリケヌション局デヌタブロックも備えおおり、これらが䞀緒になっおAPDUプロトコルデヌタナニットを圢成したす。







結果のAPDUをより詳现に怜蚎しおください。



APCI





ASDU





<100> C_IC_NA_1ぞの応答ずしお、芁求に察する確認で応答し、被制埡ステヌションに保存されおいるプロセス情報オブゞェクトを転送し、アクティベヌションを完了する必芁がありたす。

確認を送信するには、ASDU <100> C_IC_NA_1に転送の理由CauseTXを瀺すバむト、7に等しい倀を曞き蟌む必芁がありたす。アクティベヌション完了を送信するには、転送の理由CauseTXに10に等しいバむトを曞き蟌む必芁がありたす。



スケッチ
  case 00://  txcnt=txcnt+02; //   iec104ReciveArray[0]=iec104ReciveArray[0]; iec104ReciveArray[1]=iec104ReciveArray[1]; iec104ReciveArray[2]=lowByte(txcnt);//TX L iec104ReciveArray[3]=highByte(txcnt);//TX H iec104ReciveArray[4]=lowByte(rxcnt);//RX L iec104ReciveArray[5]=highByte(rxcnt);//RX H iec104ReciveArray[6]=100;//  iec104ReciveArray[7]=01; iec104ReciveArray[8]=7;//cause Actcon iec104ReciveArray[9]=00;//OA iec104ReciveArray[10]=01;//Addr iec104ReciveArray[11]=00;//Addr iec104ReciveArray[12]=00;//IOA iec104ReciveArray[13]=00;//IOA iec104ReciveArray[14]=00;//IOA iec104ReciveArray[15]=20;//IOA, QOI MessageLength = iec104ReciveArray[1]+2; delay(100); client.write(iec104ReciveArray, MessageLength); txcnt=txcnt+2;//    //          iec104ReciveArray[0]=iec104ReciveArray[0]; iec104ReciveArray[1]=14;// APDU=APCI(4)+ ASDU(10) iec104ReciveArray[2]=lowByte(txcnt); iec104ReciveArray[3]=highByte(txcnt); iec104ReciveArray[4]=lowByte(rxcnt); iec104ReciveArray[5]=highByte(rxcnt); iec104ReciveArray[6]=1;//type 1 iec104ReciveArray[7]=01;//sq iec104ReciveArray[8]=20;//Cause Inrogen iec104ReciveArray[9]=00;//AO iec104ReciveArray[10]=01;//Adress iec104ReciveArray[11]=00;//Adress iec104ReciveArray[12]=iecData[0];//IOA iec104ReciveArray[13]=iecData[1];//IOA iec104ReciveArray[14]=0;//IOA iec104ReciveArray[15]=iecData[2];//value [DATA 1] MessageLength = iec104ReciveArray[1]+2; client.write(iec104ReciveArray, MessageLength); txcnt=txcnt+2; iec104ReciveArray[0]=iec104ReciveArray[0]; iec104ReciveArray[1]=14; iec104ReciveArray[2]=lowByte(txcnt); iec104ReciveArray[3]=highByte(txcnt); iec104ReciveArray[4]=lowByte(rxcnt); iec104ReciveArray[5]=highByte(rxcnt); iec104ReciveArray[6]=1;//type 1 bool iec104ReciveArray[7]=01; iec104ReciveArray[8]=20;//Cause Inrogen iec104ReciveArray[9]=00; iec104ReciveArray[10]=01; iec104ReciveArray[11]=00; iec104ReciveArray[12]=iecData[3]; iec104ReciveArray[13]=iecData[4]; iec104ReciveArray[14]=0; iec104ReciveArray[15]=iecData[5]; MessageLength = iec104ReciveArray[1]+2; client.write(iec104ReciveArray, MessageLength); delay(5); txcnt=txcnt+2; iec104ReciveArray[0]=iec104ReciveArray[0]; iec104ReciveArray[1]=22; iec104ReciveArray[2]=lowByte(txcnt); iec104ReciveArray[3]=highByte(txcnt); iec104ReciveArray[4]=lowByte(rxcnt); iec104ReciveArray[5]=highByte(rxcnt); iec104ReciveArray[6]=11;//type 11 int iec104ReciveArray[7]=02;//sq iec104ReciveArray[8]=20;//Cause Inrogen iec104ReciveArray[9]=00;//AO iec104ReciveArray[10]=01;//Adress iec104ReciveArray[11]=00;//Adress iec104ReciveArray[12]=iecData[6];//IOA iec104ReciveArray[13]=iecData[7];//IOA iec104ReciveArray[14]=0;//IOA iec104ReciveArray[15]=iecData[8];//value [DATA 1] iec104ReciveArray[16]=iecData[9];//value [DATA 1] iec104ReciveArray[17]=iecData[10];//QDS iec104ReciveArray[18]=iecData[11];//IOA iec104ReciveArray[19]=iecData[12];//OA iec104ReciveArray[20]=0;//IOA iec104ReciveArray[21]=iecData[13];//value [DATA 2] iec104ReciveArray[22]=iecData[14];//value [DATA 2] iec104ReciveArray[23]=iecData[15];//IOA QDS MessageLength = iec104ReciveArray[1]+2; client.write(iec104ReciveArray, MessageLength); delay(5); txcnt=txcnt+2; iec104ReciveArray[0]=iec104ReciveArray[0]; iec104ReciveArray[1]=26; iec104ReciveArray[2]=lowByte(txcnt); iec104ReciveArray[3]=highByte(txcnt); iec104ReciveArray[4]=lowByte(rxcnt); iec104ReciveArray[5]=highByte(rxcnt); iec104ReciveArray[6]=13;//type 13 Float iec104ReciveArray[7]=02;//sq iec104ReciveArray[8]=20;//Cause Inrogen iec104ReciveArray[9]=00;//AO iec104ReciveArray[10]=01;//Adress iec104ReciveArray[11]=00;//Adress iec104ReciveArray[12]=iecData[16];//IOA iec104ReciveArray[13]=iecData[17];//IOA iec104ReciveArray[14]=0; iec104ReciveArray[15]=iecData[18];//value [DATA 1] iec104ReciveArray[16]=iecData[19];//value [DATA 1] iec104ReciveArray[17]=iecData[20];//value [DATA 1] iec104ReciveArray[18]=iecData[21];//value [DATA 1] iec104ReciveArray[19]=iecData[22];//IOA QDS iec104ReciveArray[20]=iecData[23];//IOA iec104ReciveArray[21]=iecData[24];//IOA iec104ReciveArray[22]=0;//IOA iec104ReciveArray[23]=iecData[25];//value [DATA 2] iec104ReciveArray[24]=iecData[26];//value [DATA 2] iec104ReciveArray[25]=iecData[27];//value [DATA 2] iec104ReciveArray[26]=iecData[28];//value [DATA 2] iec104ReciveArray[27]=iecData[29];//IOA QDS MessageLength = iec104ReciveArray[1]+2; client.write(iec104ReciveArray, MessageLength); txcnt=txcnt+2; //   iec104ReciveArray[0]=iec104ReciveArray[0]; iec104ReciveArray[1]=iec104ReciveArray[1]; iec104ReciveArray[2]=lowByte(txcnt); iec104ReciveArray[3]=highByte(txcnt); iec104ReciveArray[4]=lowByte(rxcnt); iec104ReciveArray[5]=highByte(rxcnt); iec104ReciveArray[6]=100;//type iec104ReciveArray[7]=01;//sq iec104ReciveArray[8]=10;//cause AckTerm iec104ReciveArray[9]=00; iec104ReciveArray[10]=01; iec104ReciveArray[11]=00; iec104ReciveArray[12]=00; iec104ReciveArray[13]=00; iec104ReciveArray[14]=00; iec104ReciveArray[15]=20; MessageLength = iec104ReciveArray[1]+2; client.write(iec104ReciveArray, MessageLength); iec104ReciveArray[6]=00;//       break;
      
      







スケッチを曎新した埌、次の亀換順序を確認したす。





接続の確立、デヌタ送信の芁求、確認、制埡局からのステヌションの䞀般的な問い合わせの芁求、初期化の完了、制埡されたステヌションの方向でのステヌションの䞀般的な問い合わせの芁求、䞀般的な問い合わせの確認、制埡ステヌションで利甚可胜なすべおの信号の倀の送信、䞀般的な問い合わせおよび未知の完了APCIフォヌマットS

ステヌションポヌリング芁求は、監芖されおいるステヌションの方向に発行されたす。

-「初期化の終了」が被制埡ステヌションから受信された堎合、たたは

-䞭倮局がチャネルの損倱デヌタリンクレむダヌの芁求の繰り返しの倱敗ずその埌の埩元を怜出した堎合。



4.準備ずデヌタ転送



APCIのみで構成されるAPDU Sフォヌマットナニットは、採甚されたAPDU Iフォヌマットを確認するためのものです。 Sフォヌマットの堎合、バむト1およびバむト2のサヌビスフィヌルドの䞊䜍7ビットは䜿甚されず、バむト3䞊䜍7ビットおよびバむト4は受信メッセヌゞの珟圚の数を決定したす。







この堎合、ブロックSは、制埡マスタヌステヌションが、制埡マスタヌステヌションの偎で定矩されたタむムアりトt3を超えない䞀定時間内にデヌタを受信する準備ができおいるこずを瀺したす。 ぀たり、マスタヌステヌションから「デヌタを受信する準備ができたした」 次に、転送するデヌタずその取埗元に泚意する必芁がありたす。



䜕を送信できたすか IEC 870-5-104には、いく぀かのタむプの情報が定矩されおいたす。





写真




この䟋では、1、11、および13の機胜単䞀芁玠、枬定はスケヌラブル、枬定は浮動小数点を䜿甚した短い圢匏の䟋による制埡情報の送信を考慮しおいたす。 デヌタはランダムに生成されたす。 たた、各送信信号に品質バむトがあるこずを考慮する必芁がありたす。







信号品質を決定するための簡単なアルゎリズム





スケッチ
 void SetQDS(int currvalue, int i,bool zam)//   { if (zam==0)//? { if (currvalue==previusValue[i])//  ? { previusValue[i]=currvalue; counter[i]+=1; if (counter[i]>=1000) { qds[i]=64;// NT counter[i]=0; } } else { qds[i]=0; counter[i]=0; previusValue[i]=currvalue; } } else { qds[i]=48;// SB, BL } }
      
      







たた、信号ごずに䞀意のIOA識別子が存圚するこずを考慮する必芁がありたす。電力業界では、これらのアドレスを次のように配垃するのが䞀般的です。





送信のために信号倀をアレむに転送するには、EEPROMラむブラリを䜿甚したす。



スケッチ
 void EEPROM_float_write(int addr, float val,int IOA,int number,bool subs) //    EEPROM,  ,  ,    ,  { SetQDS(val,number, subs);//   byte *x = (byte *)&val;//float -->byte byte *xxx = (byte *)&IOA;//  IOA for(int jj = 0; jj <2; jj++) { EEPROM.write(addr,xxx[jj]);//  EEPROM     2  addr+=1; } for(byte i = 0; i < 4; i++) //  float  4  { EEPROM.write(addr, x[i]); //  float  4  addr+=1; } EEPROM.write(addr, qds[number]);//     if (addr == EEPROM.length()) { addr = 0; } }
      
      







したがっお、監芖ステヌションからSたたはIフォヌマットのAPDU確認を受信するず、送信フレヌムの数を増やすこずを忘れずに、䜿甚可胜なデヌタの送信を開始できたす。





スケッチ
 #include <eeprom.h> #include <Ethernet.h> #include <eeprom.h> byte mac[] = {0x90, 0xA2, 0xDA, 0x0E, 0x94, 0xB7 }; IPAddress ip(172, 16, 7, 1); IPAddress gateway(172, 16,7, 0); IPAddress subnet(255, 255, 0, 0); EthernetClient client; EthernetServer iec104Server(2404); int TypeQuerry, MessageLength; uint8_t iec104ReciveArray[128]; int counter[6];//   int qds[6];//      int previusValue[6];//     NT word iecData[256];//     int ASDU;//     int txcnt, rxcnt;//     void setup() { //  2404  Ethernet.begin(mac, ip, gateway, subnet); Serial.begin(9600); } void EEPROM_float_write(int addr, float val,int IOA,int number,bool zam) //      Float  13 { SetQDS(val,number,zam);//  byte *x = (byte *)&val; byte *xxx = (byte *)&IOA; for(int jj = 0; jj <2; jj++)//  IOA  2  { EEPROM.write(addr,xxx[jj]); addr+=1; } for(byte i = 0; i < 4; i++)//  float  4  { EEPROM.write(addr, x[i]); addr+=1; } EEPROM.write(addr, qds[number]); if (addr == EEPROM.length()) { addr = 0; } } void EEPROM_byte_write(int addr, bool val,int IOA,int number,bool zam) //      Bool  1 { SetQDS(val,number,zam);//  byte c=val+qds[number]; byte *x = (byte *)&c; byte *xxxx = (byte *)&IOA; for(int jj = 0; jj <2; jj++) //  IOA  2  { EEPROM.write(addr,xxxx[jj]); addr+=1; } for(byte i = 0; i < 1; i++) //  bool +    1  { EEPROM.write(addr, x[i]); } if (addr == EEPROM.length()) { addr = 0; } } void EEPROM_int_write(int addr, int val, int IOA,int number,bool zam) //      Int  11 { SetQDS(val,number,zam); //  byte *x = (byte *)&val; byte *xx = (byte *)&IOA; for(int jj = 0; jj <2; jj++)//  IOA  2  { EEPROM.write(addr,xx[jj]); addr+=1; } for(byte i = 0; i < 2; i++)//  int  2 a { EEPROM.write(addr, x[i]); addr+=1; } EEPROM.write(addr, qds[number]); if (addr == EEPROM.length()) { addr = 0; } } //   void SetQDS(int currvalue, int i,bool zam)// ,    ,  { if (zam==0)//? { if (currvalue==previusValue[i])//  ? { previusValue[i]=currvalue; counter[i]+=1; if (counter[i]>=1000) { qds[i]=64;//  NT counter[i]=0; } } else { qds[i]=0; counter[i]=0; previusValue[i]=currvalue; } } else { qds[i]=48;//     } } void loop() { //   1,11,13  // : (  EEPROM,  , IOA ,  ) EEPROM_byte_write(0,0,4096,0,0); EEPROM_byte_write(3,random(0, 2),4097,1,1); EEPROM_int_write(6, 67,8192,2,1); EEPROM_int_write(11, random(10, 20),8193,3,0); EEPROM_float_write(16, random(-1000, 2000),8194,4,1); EEPROM_float_write(23, 78.66f,8195,5,1); client = iec104Server.available(); if(client.available()) { delay(100); int i = 0; while(client.available()) { iec104ReciveArray[i] = client.read();//     i++; } ASDU=iec104ReciveArray[6];// ASDU? switch (ASDU) { case 100://  TypeQuerry=iec104ReciveArray[2]-word(iec104ReciveArray[3],iec104ReciveArray[2]); rxcnt+=2;//    break; case 0: TypeQuerry=iec104ReciveArray[2];//   break; default : TypeQuerry=iec104ReciveArray[2]; break; } for(byte z = 0; z <64; z++) //   { iecData[z]= EEPROM.read(z); } //  APDU switch(TypeQuerry) { case 07://APDU STARTDT rxcnt=0; txcnt=0; iec104ReciveArray[0]=iec104ReciveArray[0];//  ,   START2 = 68h; iec104ReciveArray[1]=iec104ReciveArray[1];// APDU iec104ReciveArray[2]=11;//STARTDT con iec104ReciveArray[3]=0; iec104ReciveArray[4]=0; iec104ReciveArray[5]=0; MessageLength = iec104ReciveArray[1]+2;//  client.write(iec104ReciveArray, MessageLength);//  // iec104ReciveArray[0]=iec104ReciveArray[0];//  ,   START2 = 68h; iec104ReciveArray[1]=14;// APDU iec104ReciveArray[2]=0;//, TX L iec104ReciveArray[3]=0;//TX H iec104ReciveArray[4]=0;//RX L iec104ReciveArray[5]=0;//RX H iec104ReciveArray[6]=70;//type End of Init iec104ReciveArray[7]=01;//sq iec104ReciveArray[8]=04;//cause Init iec104ReciveArray[9]=00;//AO iec104ReciveArray[10]=01;//Adress iec104ReciveArray[11]=00;//Adress iec104ReciveArray[12]=00;//IOA iec104ReciveArray[13]=00;//IOA iec104ReciveArray[14]=00;//IOA iec104ReciveArray[15]=129;//IOA, COI MessageLength = iec104ReciveArray[1]+2; client.write(iec104ReciveArray, MessageLength); //      iec104ReciveArray[0]=iec104ReciveArray[0]; iec104ReciveArray[1]=14;// APDU iec104ReciveArray[2]=2;//TX L iec104ReciveArray[3]=0;//TX H iec104ReciveArray[4]=0;//RX L iec104ReciveArray[5]=0;//RX H iec104ReciveArray[6]=100;//   iec104ReciveArray[7]=01; iec104ReciveArray[8]=6;//cause Act iec104ReciveArray[9]=00; iec104ReciveArray[10]=01; iec104ReciveArray[11]=00; iec104ReciveArray[12]=00; iec104ReciveArray[13]=00; iec104ReciveArray[14]=00; iec104ReciveArray[15]=20;//IOA, QOI  MessageLength = iec104ReciveArray[1]+2; client.write(iec104ReciveArray, MessageLength); txcnt=txcnt+02; break; case 00://  txcnt=txcnt+02; //   iec104ReciveArray[0]=iec104ReciveArray[0]; iec104ReciveArray[1]=iec104ReciveArray[1]; iec104ReciveArray[2]=lowByte(txcnt);//TX L iec104ReciveArray[3]=highByte(txcnt);//TX H iec104ReciveArray[4]=lowByte(rxcnt);//RX L iec104ReciveArray[5]=highByte(rxcnt);//RX H iec104ReciveArray[6]=100;//  iec104ReciveArray[7]=01; iec104ReciveArray[8]=7;//cause Actcon iec104ReciveArray[9]=00;//OA iec104ReciveArray[10]=01;//Addr iec104ReciveArray[11]=00;//Addr iec104ReciveArray[12]=00;//IOA iec104ReciveArray[13]=00;//IOA iec104ReciveArray[14]=00;//IOA iec104ReciveArray[15]=20;//IOA, QOI MessageLength = iec104ReciveArray[1]+2; delay(100); client.write(iec104ReciveArray, MessageLength); txcnt=txcnt+2;//    //          iec104ReciveArray[0]=iec104ReciveArray[0]; iec104ReciveArray[1]=14;// APDU=APCI(4)+ ASDU(10) iec104ReciveArray[2]=lowByte(txcnt); iec104ReciveArray[3]=highByte(txcnt); iec104ReciveArray[4]=lowByte(rxcnt); iec104ReciveArray[5]=highByte(rxcnt); iec104ReciveArray[6]=1;//type 1 iec104ReciveArray[7]=01;//sq iec104ReciveArray[8]=20;//Inrogen iec104ReciveArray[9]=00;//AO iec104ReciveArray[10]=01;//Adress iec104ReciveArray[11]=00;//Adress iec104ReciveArray[12]=iecData[0];//IOA iec104ReciveArray[13]=iecData[1];//IOA iec104ReciveArray[14]=0;//IOA iec104ReciveArray[15]=iecData[2];//value [DATA 1] MessageLength = iec104ReciveArray[1]+2; client.write(iec104ReciveArray, MessageLength); txcnt=txcnt+2; iec104ReciveArray[0]=iec104ReciveArray[0]; iec104ReciveArray[1]=14; iec104ReciveArray[2]=lowByte(txcnt); iec104ReciveArray[3]=highByte(txcnt); iec104ReciveArray[4]=lowByte(rxcnt); iec104ReciveArray[5]=highByte(rxcnt); iec104ReciveArray[6]=1; iec104ReciveArray[7]=01; iec104ReciveArray[8]=20; iec104ReciveArray[9]=00; iec104ReciveArray[10]=01; iec104ReciveArray[11]=00; iec104ReciveArray[12]=iecData[3]; iec104ReciveArray[13]=iecData[4]; iec104ReciveArray[14]=0; iec104ReciveArray[15]=iecData[5]; MessageLength = iec104ReciveArray[1]+2; client.write(iec104ReciveArray, MessageLength); delay(5); txcnt=txcnt+2; iec104ReciveArray[0]=iec104ReciveArray[0]; iec104ReciveArray[1]=22; iec104ReciveArray[2]=lowByte(txcnt); iec104ReciveArray[3]=highByte(txcnt); iec104ReciveArray[4]=lowByte(rxcnt); iec104ReciveArray[5]=highByte(rxcnt); iec104ReciveArray[6]=11;//type 11 iec104ReciveArray[7]=02;//sq iec104ReciveArray[8]=20;//cause iec104ReciveArray[9]=00;//AO iec104ReciveArray[10]=01;//Adress iec104ReciveArray[11]=00;//Adress iec104ReciveArray[12]=iecData[6];//IOA iec104ReciveArray[13]=iecData[7];//IOA iec104ReciveArray[14]=0;//IOA iec104ReciveArray[15]=iecData[8];//value [DATA 1] iec104ReciveArray[16]=iecData[9];//value [DATA 1] iec104ReciveArray[17]=iecData[10];//QDS iec104ReciveArray[18]=iecData[11];//IOA iec104ReciveArray[19]=iecData[12];//OA iec104ReciveArray[20]=0;//IOA iec104ReciveArray[21]=iecData[13];//value [DATA 2] iec104ReciveArray[22]=iecData[14];//value [DATA 2] iec104ReciveArray[23]=iecData[15];//IOA QDS MessageLength = iec104ReciveArray[1]+2; client.write(iec104ReciveArray, MessageLength); delay(5); txcnt=txcnt+2; iec104ReciveArray[0]=iec104ReciveArray[0]; iec104ReciveArray[1]=26; iec104ReciveArray[2]=lowByte(txcnt); iec104ReciveArray[3]=highByte(txcnt); iec104ReciveArray[4]=lowByte(rxcnt); iec104ReciveArray[5]=highByte(rxcnt); iec104ReciveArray[6]=13;//type 13 iec104ReciveArray[7]=02;//sq iec104ReciveArray[8]=20;//cause iec104ReciveArray[9]=00;//AO iec104ReciveArray[10]=01;//Adress iec104ReciveArray[11]=00;//Adress iec104ReciveArray[12]=iecData[16];//IOA iec104ReciveArray[13]=iecData[17];//IOA iec104ReciveArray[14]=0; iec104ReciveArray[15]=iecData[18];//value [DATA 1] iec104ReciveArray[16]=iecData[19];//value [DATA 1] iec104ReciveArray[17]=iecData[20];//value [DATA 1] iec104ReciveArray[18]=iecData[21];//value [DATA 1] iec104ReciveArray[19]=iecData[22];//IOA QDS iec104ReciveArray[20]=iecData[23];//IOA iec104ReciveArray[21]=iecData[24];//IOA iec104ReciveArray[22]=0;//IOA iec104ReciveArray[23]=iecData[25];//value [DATA 2] iec104ReciveArray[24]=iecData[26];//value [DATA 2] iec104ReciveArray[25]=iecData[27];//value [DATA 2] iec104ReciveArray[26]=iecData[28];//value [DATA 2] iec104ReciveArray[27]=iecData[29];//IOA QDS MessageLength = iec104ReciveArray[1]+2; client.write(iec104ReciveArray, MessageLength); txcnt=txcnt+2; //   iec104ReciveArray[0]=iec104ReciveArray[0]; iec104ReciveArray[1]=iec104ReciveArray[1]; iec104ReciveArray[2]=lowByte(txcnt); iec104ReciveArray[3]=highByte(txcnt); iec104ReciveArray[4]=lowByte(rxcnt); iec104ReciveArray[5]=highByte(rxcnt); iec104ReciveArray[6]=100;//type iec104ReciveArray[7]=01;//sq iec104ReciveArray[8]=10;//cause AckTerm iec104ReciveArray[9]=00; iec104ReciveArray[10]=01; iec104ReciveArray[11]=00; iec104ReciveArray[12]=00; iec104ReciveArray[13]=00; iec104ReciveArray[14]=00; iec104ReciveArray[15]=20; MessageLength = iec104ReciveArray[1]+2; client.write(iec104ReciveArray, MessageLength); iec104ReciveArray[6]=00;//       break; //APDU S case 01: txcnt=word(iec104ReciveArray[5],iec104ReciveArray[4]); iec104ReciveArray[0]=iec104ReciveArray[0]; iec104ReciveArray[1]=14; iec104ReciveArray[2]=lowByte(txcnt); iec104ReciveArray[3]=highByte(txcnt); iec104ReciveArray[4]=lowByte(rxcnt); iec104ReciveArray[5]=highByte(rxcnt); iec104ReciveArray[6]=1;//type 1 iec104ReciveArray[7]=01;//sq iec104ReciveArray[8]=01;//cause Cycl iec104ReciveArray[9]=00;//AO iec104ReciveArray[10]=01;//Adress iec104ReciveArray[11]=00;//Adress iec104ReciveArray[12]=iecData[0];//IOA iec104ReciveArray[13]=iecData[1];//IOA iec104ReciveArray[14]=0;//IOA iec104ReciveArray[15]=iecData[2];//value [DATA 1] MessageLength = iec104ReciveArray[1]+2; client.write(iec104ReciveArray, MessageLength); delay(5); txcnt=txcnt+2; iec104ReciveArray[0]=iec104ReciveArray[0]; iec104ReciveArray[1]=14; iec104ReciveArray[2]=lowByte(txcnt); iec104ReciveArray[3]=highByte(txcnt); iec104ReciveArray[4]=lowByte(rxcnt); iec104ReciveArray[5]=highByte(rxcnt); iec104ReciveArray[6]=1;//type 1 Bool iec104ReciveArray[7]=01;//sq iec104ReciveArray[8]=01;//cause Cycl iec104ReciveArray[9]=00;//AO iec104ReciveArray[10]=01;//Adress iec104ReciveArray[11]=00;//Adress iec104ReciveArray[12]=iecData[3];//IOA iec104ReciveArray[13]=iecData[4];//IOA iec104ReciveArray[14]=0;//IOA iec104ReciveArray[15]=iecData[5];//value [DATA 1] MessageLength = iec104ReciveArray[1]+2; client.write(iec104ReciveArray, MessageLength); delay(5); txcnt=txcnt+2; iec104ReciveArray[0]=iec104ReciveArray[0]; iec104ReciveArray[1]=22; iec104ReciveArray[2]=lowByte(txcnt); iec104ReciveArray[3]=highByte(txcnt); iec104ReciveArray[4]=lowByte(rxcnt); iec104ReciveArray[5]=highByte(rxcnt); iec104ReciveArray[6]=11;//type 11 Int iec104ReciveArray[7]=02;//sq iec104ReciveArray[8]=01;//cause Cycl iec104ReciveArray[9]=00;//AO iec104ReciveArray[10]=01;//Adress iec104ReciveArray[11]=00;//Adress iec104ReciveArray[12]=iecData[6];//IOA iec104ReciveArray[13]=iecData[7];//IOA iec104ReciveArray[14]=0;//IOA iec104ReciveArray[15]=iecData[8];//value [DATA 1] iec104ReciveArray[16]=iecData[9];//value [DATA 1] iec104ReciveArray[17]=iecData[10];//QDS iec104ReciveArray[18]=iecData[11];//IOA iec104ReciveArray[19]=iecData[12];//OA iec104ReciveArray[20]=0;//IOA iec104ReciveArray[21]=iecData[13];//value [DATA 2] iec104ReciveArray[22]=iecData[14];//value [DATA 2] iec104ReciveArray[23]=iecData[15];//IOA QDS MessageLength = iec104ReciveArray[1]+2; client.write(iec104ReciveArray, MessageLength); delay(5); txcnt=txcnt+2; iec104ReciveArray[0]=iec104ReciveArray[0]; iec104ReciveArray[1]=26; iec104ReciveArray[2]=lowByte(txcnt); iec104ReciveArray[3]=highByte(txcnt); iec104ReciveArray[4]=lowByte(rxcnt); iec104ReciveArray[5]=highByte(rxcnt); iec104ReciveArray[6]=13;//type 13 Float iec104ReciveArray[7]=02;//sq iec104ReciveArray[8]=01;//cause Cycl iec104ReciveArray[9]=00;//AO iec104ReciveArray[10]=01;//Adress iec104ReciveArray[11]=00;//Adress iec104ReciveArray[12]=iecData[16];//IOA iec104ReciveArray[13]=iecData[17];//IOA iec104ReciveArray[14]=0; iec104ReciveArray[15]=iecData[18];//value [DATA 1] iec104ReciveArray[16]=iecData[19];//value [DATA 1] iec104ReciveArray[17]=iecData[20];//value [DATA 1] iec104ReciveArray[18]=iecData[21];//value [DATA 1] iec104ReciveArray[19]=iecData[22];//IOA QDS iec104ReciveArray[20]=iecData[23];//IOA iec104ReciveArray[21]=iecData[24];//IOA iec104ReciveArray[22]=0;//IOA iec104ReciveArray[23]=iecData[25];//value [DATA 2] iec104ReciveArray[24]=iecData[26];//value [DATA 2] iec104ReciveArray[25]=iecData[27];//value [DATA 2] iec104ReciveArray[26]=iecData[28];//value [DATA 2] iec104ReciveArray[27]=iecData[29];//IOA QDS MessageLength = iec104ReciveArray[1]+2; client.write(iec104ReciveArray, MessageLength); txcnt=txcnt; break; case 67: //TESTFR iec104ReciveArray[0]=iec104ReciveArray[0]; iec104ReciveArray[1]=iec104ReciveArray[1]; iec104ReciveArray[2] =131; //TESTFR con iec104ReciveArray[3] =0; iec104ReciveArray[4] =0; iec104ReciveArray[5] =0; MessageLength = iec104ReciveArray[1]+2; delay(10); client.write(iec104ReciveArray, MessageLength); iec104ReciveArray[0]=iec104ReciveArray[0]; iec104ReciveArray[1]=26;// APDU iec104ReciveArray[2]=lowByte(txcnt); iec104ReciveArray[3]=highByte(txcnt); iec104ReciveArray[4]=lowByte(rxcnt); iec104ReciveArray[5]=highByte(rxcnt); iec104ReciveArray[6]=13;//type 13 iec104ReciveArray[7]=02;//sq iec104ReciveArray[8]=03;//spont iec104ReciveArray[9]=00;//AO iec104ReciveArray[10]=01;//Adress iec104ReciveArray[11]=00;//Adress iec104ReciveArray[12]=iecData[16];//IOA iec104ReciveArray[13]=iecData[17];//IOA iec104ReciveArray[14]=0; iec104ReciveArray[15]=iecData[18];//value [DATA 1] iec104ReciveArray[16]=iecData[19];//value [DATA 1] iec104ReciveArray[17]=iecData[20];//value [DATA 1] iec104ReciveArray[18]=iecData[21];//value [DATA 1] iec104ReciveArray[19]=iecData[22];//IOA QDS iec104ReciveArray[20]=iecData[23];//IOA iec104ReciveArray[21]=iecData[24];//IOA iec104ReciveArray[22]=0;//IOA iec104ReciveArray[23]=iecData[25]; iec104ReciveArray[24]=iecData[26]; iec104ReciveArray[25]=iecData[27]; iec104ReciveArray[26]=iecData[28]; iec104ReciveArray[27]=iecData[29];//IOA QDS MessageLength = iec104ReciveArray[1]+2; client.write(iec104ReciveArray, MessageLength); break; } } }
      
      







Wiresharkにスケッチをロヌドした埌、デヌタ転送が最終的に開始されたこずを確認したす。



以䞋は、ASDU <100> M_SP_NA_1シングルトン衚瀺の構造の説明です。







TypeId-情報のタむプ。

SQ-倉数構造の分類子。



2぀のデヌタブロック構造が想定されたす



。1. i個の情報オブゞェクトを含むブロック。各オブゞェクトには1぀の情報芁玠たたは芁玠の1぀の組み合わせが含たれたす。倉数構造SQ単䞀/シヌケンスの分類子の最䞊䜍ビットは0で、残りの7ビットは数倀iを指定したす。



2. j個の芁玠たたは情報芁玠の同じ組み合わせを含む1぀の情報オブゞェクトを含むブロック。 SQ修食子の最䞊䜍ビット27 = 80hは1で、残りの7ビットは数倀jを指定したす。



写真




CauseTx-転送の理由。



写真




Addr-スレヌブのアドレスりィザヌドの構成時に指定。

IOAは -このアドレス監芖ステヌションでのオブゞェクト情報のアドレスは、あなたのタグネクタむたす

SIQ送信される信号の品質を- 。



機胜ブロック<11> M_ME_NB_1のASDU構造



Wireshark




受信したデヌタに応じお、マスタヌはSフォヌマットブロックを送信し、プロセスは監芖察象スレヌブデバむスがフレヌムの送信を停止するたでルヌプしたす。



5.テスト手順



テスト手順は、トランスポヌト接続の状態を監芖するために䜿甚されたす。制埡時間t3の間にフレヌムI、U、Sが受信されなかった堎合、IP接続の「アクティビティ」に関係なく手順が実行されたす。時間t3は承認の察象であり、「長時間のダりンタむムが発生した堎合のテストブロックの送信のタむムアりト」ず呌ばれたす。テスト手順は、テストAPDUを送信するこずで実装されTESTFR = act、APDUを䜿甚しお受信ステヌションで確認されたすTESTFR = con。



写真




Wireshark




APDUタむプのバむトの倀が60ネットワヌクTESTFRに等しい制埡マスタヌステヌションからAPDUが到着した堎合、これは時間t3I、U、Sの間に制埡ステヌションからフレヌムが受信されなかったこずを瀺したす、および時間t1の間に確認で応答しない堎合、接続は切断されたす。



スケッチ
 case 67: iec104ReciveArray[0]=iec104ReciveArray[0];//  ,   START2 = 68h; iec104ReciveArray[1]=iec104ReciveArray[1];// APDU LENGHT iec104ReciveArray[2] = 131; //TESTDT con iec104ReciveArray[3] =0; iec104ReciveArray[4] =0; iec104ReciveArray[5] =0; MessageLength = iec104ReciveArray[1]+2;//   + 2  Start68H and Lenght delay(10); client.write(iec104ReciveArray, MessageLength);
      
      







Wireshark




誰もが興味を持っおいるのであれば、それですべおです。次の蚘事では、䟋ずしおArduinoを䜿甚しお、マスタヌステヌションからのIEC 670-5-104プロトコルを怜蚎したす。



All Articles