2024年1月18日 星期四

ESP32 MFRC522 Write / Read 讀取與寫入資料 Sector / Block + Node-Red UI控制Sector / Block 讀寫

 ESP32 MFRC522 Write / Read 讀取與寫入資料 Sector / Block  + Node-Red UI控制Sector / Block 讀寫












每個區段的區塊3也叫做控制區塊(Sector Trailer, Trailer Block或Security Block),如果把上圖的資料結構想像成16層大樓,控制區塊相當於每一層樓的密碼鎖;進、出該層樓必須先輸入正確的密碼,而且每層樓都有兩組密碼。

控制區塊包含金鑰A和金鑰B兩組密碼(各6位元組),以及存取控制位元(4位元組,但僅使用前3位元組)


RFID卡內部有1KB的EEPROM記憶體,為了妥善管理並達到一卡多用的功能,這個記憶體空間被劃分成16個區段(sector),每個區段有4個區塊(block)區段0的區塊0包含卡片的唯一識別碼(UID,也稱為「製造商識別碼」,Manufacturer Code)。

參考 https://swf.com.tw/?p=941


/*
MFRC522物件.PCD_Authenticate():驗證金鑰,相當於比對輸入密碼和卡片裡的密碼,唯通過驗證才能存取區段資料。
MFRC522物件.GetStatusCodeName():取得狀態碼的名稱
MFRC522物件.MIFARE_Read():讀取指定區塊的內容
MFRC522物件.MIFARE_Write():在指定區塊寫入資料
MFRC522物件.PICC_DumpMifareClassicSectorToSerial():在序列埠監控視窗顯示指定的區段內容
*/

//wifi &  MQTT
#include <WiFi.h>             //定義Wifi 程式庫
#include <PubSubClient.h>      //定義MQTT Pub發行 Sub 訂閱 程式庫
//RC522 SPI Mode
#include <SPI.h>          //定義MFRC522 RFID read 與 ESP32 介面
#include <MFRC522.h>      //定義MFRC522 RFID read程式庫

#define RST_PIN    27     // Reset腳
#define SS_PIN     5     // 晶片選擇腳

//GPIO 2 D1 Build in LED
#define LED 2                //定義LED接腳
//定義MFRC522 RFID read 與 ESP32 介面 接腳連接Pin assign
/* Wiring RFID RC522 module  
=============================================================================
GND     = GND   3.3V    = 3.3V
The following table shows the typical pin layout used:
 *             MFRC522      ESP32    
 *             Reader/PCD            
 * Signal      Pin          Pin        
 * -----------------------------------
 * RST/Reset   RST          GPIO27  
 * SPI SS      SDA(SS)      GPIO5    
 * SPI MOSI    MOSI         GPIO23    
 * SPI MISO    MISO         GPIO19    
 * SPI SCK     SCK          GPIO18    
 *
[1] (1, 2) Configurable, typically defined as RST_PIN in sketch/program.
[2] (1, 2) Configurable, typically defined as SS_PIN in sketch/program.
[3] The SDA pin might be labeled SS on some/older MFRC522 boards
=============================================================================
*/
// WiFi SSID password , SSID 和密碼進行Wi-Fi 設定
//const char *ssid = "TOTOLINK_A3002MU"; // Enter your Wi-Fi name
//const char *password = "24063173";  // Enter Wi-Fi password
const char *ssid = "dlink-103A"; // Enter your Wi-Fi name
const char *password = "bdcce12882";  // Enter Wi-Fi password


// MQTT Broker
const char *mqtt_broker = "broker.hivemq.com"; //broker.mqtt-dashboard.com
const char *topic1 = "alex9ufo/RFID/read";
const char *topic2 = "alex9ufo/RFID/write";
const char *topic3 = "alex9ufo/RFID/back";

const char *mqtt_username = "alex9ufo";
const char *mqtt_password = "public";
const int mqtt_port = 1883;

WiFiClient espClient;
PubSubClient client(espClient);
//定義 MQTT 發行及訂閱需要的變數
String json = "";
char jsonChar[50];  //client.publish
bool toggle=false;
bool WR_flag=false;
bool RD_flag=false;

String text="";

MFRC522 mfrc522(SS_PIN, RST_PIN);    // 建立MFRC522物件
MFRC522::MIFARE_Key key;  // 儲存金鑰

byte sector = 0;   // 指定讀寫的「區段」,可能值:0~15
byte block = 0;     // 指定讀寫的「區塊」,可能值:0~3
byte blockData[16] = "Keep Hacking!";   // 最多可存入16個字元
// 若要清除區塊內容,請寫入16個 0
//byte blockData[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

// 暫存讀取區塊內容的陣列,MIFARE_Read()方法要求至少要18位元組空間,來存放16位元組。
byte buffer[18];

MFRC522::StatusCode status;
//====================================================  
/*** 位元組陣列轉儲為串列的十六進位值
 * 這個副程式把讀取到的UID,用16進位顯示出來
*/
void dump_byte_array(byte *buffer, byte bufferSize) {
  for (byte i = 0; i < bufferSize; i++) {
    Serial.print(buffer[i] < 0x10 ? " 0" : " ");
    Serial.print(buffer[i], HEX);
  }
}
//===========================================================
String printHex(byte *buffer, byte bufferSize) {
      String id = "";
      for (byte i = 0; i < bufferSize; i++) {
        id += buffer[i] < 0x10 ? "0" : "";
        id += String(buffer[i], HEX);
        id +=" ";
      }
      return id;
    }
//===========================================================
void writeBlock(byte _sector, byte _block, byte _blockData[]) {
  if (_sector < 0 || _sector > 15 || _block < 0 || _block > 3) {
    // 顯示「區段或區塊碼錯誤」,然後結束函式。
    Serial.println(F("Wrong sector or block number."));
    return;
  }

  if (_sector == 0 && _block == 0) {
    // 顯示「第一個區塊只能讀取」,然後結束函式。
    Serial.println(F("First block is read-only."));
    return;
  }

  byte blockNum = _sector * 4 + _block;  // 計算區塊的實際編號(0~63)
  byte trailerBlock = _sector * 4 + 3;   // 控制區塊編號

  // 驗證金鑰
  status = (MFRC522::StatusCode) mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, trailerBlock, &key, &(mfrc522.uid));
  // 若未通過驗證…
  if (status != MFRC522::STATUS_OK) {
    // 顯示錯誤訊息
    Serial.print(F("PCD_Authenticate() failed: "));
    Serial.println(mfrc522.GetStatusCodeName(status));
    return;
  }

  // 在指定區塊寫入16位元組資料
  status = (MFRC522::StatusCode) mfrc522.MIFARE_Write(blockNum, _blockData, 16);
  // 若寫入不成功…
  if (status != MFRC522::STATUS_OK) {
    // 顯示錯誤訊息
    Serial.print(F("MIFARE_Write() failed: "));
    Serial.println(mfrc522.GetStatusCodeName(status));
    return;
  }

  // 顯示「寫入成功!」
  Serial.println(F("Data was written."));
  client.publish(topic3,"Data was written.");
}
//===========================================================
void readBlock(byte _sector, byte _block, byte _blockData[])  {
  if (_sector < 0 || _sector > 15 || _block < 0 || _block > 3) {
    // 顯示「區段或區塊碼錯誤」,然後結束函式。
    Serial.println(F("Wrong sector or block number."));
    return;
  }

  byte blockNum = _sector * 4 + _block;  // 計算區塊的實際編號(0~63)
  byte trailerBlock = _sector * 4 + 3;   // 控制區塊編號

  // 驗證金鑰
  status = (MFRC522::StatusCode) mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, trailerBlock, &key, &(mfrc522.uid));
  // 若未通過驗證…
  if (status != MFRC522::STATUS_OK) {
    // 顯示錯誤訊息
    Serial.print(F("PCD_Authenticate() failed: "));
    Serial.println(mfrc522.GetStatusCodeName(status));
    return;
  }

  byte buffersize = 18;
  status = (MFRC522::StatusCode) mfrc522.MIFARE_Read(blockNum, _blockData, &buffersize);

  // 若讀取不成功…
  if (status != MFRC522::STATUS_OK) {
    // 顯示錯誤訊息
    Serial.print(F("MIFARE_read() failed: "));
    Serial.println(mfrc522.GetStatusCodeName(status));
    return;
  }

  // 顯示「讀取成功!」
  Serial.println(F("Data was read."));
  client.publish(topic3,"Data was read.");
}

//===========================================================
//副程式  setup wifi
void setup_wifi() {
  delay(10);
  // We start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);     //print ssid
  WiFi.begin(ssid, password);  //初始化WiFi 函式庫並回傳目前的網路狀態
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }   //假設 wifi 未連接 show ………

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}    

//===========================================================
// 接收MQTT主題後呼叫運行程式
//===========================================================
void callback(char *topic, byte *payload, unsigned int length) {
    Serial.print("Message arrived in topic: ");
    Serial.println(topic);
    String topic1=topic;
    Serial.print("Message: ");
    String message;
   //將接收資料轉成字串以利後續判斷
    for (int i = 0; i < length; i++) {
        message += (char) payload[i];  // Convert *byte to string
    }
    Serial.println(message);
    String  sec1;
    String  blk1;
    String  text1;
    toggle = false;

    sec1=message.substring(0,2);
    blk1=message.substring(3,5);
    text=message.substring(6);
    sector = sec1.toInt();
    block  = blk1.toInt();


    if (topic1.substring(14,18) == "read") {
      String  sec1=message.substring(0,2);
      String  blk1=message.substring(3,5);
      //String  text1=message.subString(6);
      sector = sec1.toInt();
      block  = blk1.toInt();  
      Serial.print(sec1);
      Serial.print(blk1);

      toggle=true;
      RD_flag=true;
    }
    if (topic1.substring(14,19) == "write") {
      String  sec1=message.substring(0,2);
      String  blk1=message.substring(3,5);
      text=message.substring(6);
      text.getBytes(blockData,text.length()+1);

      Serial.print(sec1);
      Serial.print(blk1);
      Serial.println(text);  
      sector = sec1.toInt();
      block  = blk1.toInt();
      toggle=true;
      WR_flag=true;
    }
    Serial.println();
    Serial.println("-------callback-----------");

}

//===========================================================
//  若目前沒有和伺服器相連,則反覆執行直到連結成功
void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    if (client.connect("esp32-client-")) {
      Serial.println("connected");
      // Subscribe
      client.subscribe("alex9ufo/RFID/read");
      client.subscribe("alex9ufo/RFID/write");      
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
      if (WiFi.status() != WL_CONNECTED)  {
        Serial.println("Reconnecting to WiFi...");
        WiFi.disconnect();
        WiFi.reconnect();
      }
    }
  }
}

//===========================================================
void setup() {
  Serial.begin(115200);
  SPI.begin();               // 初始化SPI介面
  mfrc522.PCD_Init();        // 初始化MFRC522卡片
  //======================================================
  // Connecting to a WiFi network
  setup_wifi();
  // Setting LED pin as output
  pinMode(LED, OUTPUT);
  digitalWrite(LED, LOW);  // Turn off the LED initially
  Serial.println(F("Please scan MIFARE Classic card..."));

  // 準備金鑰(用於key A和key B),出廠預設為6組 0xFF。
  for (byte i = 0; i < 6; i++) {
    key.keyByte[i] = 0xFF;
  }
  Serial.println(F("掃描卡片開始進行讀或者寫"));
  Serial.print(F("使用A和B作為KEY"));
 
  dump_byte_array(key.keyByte, MFRC522::MF_KEY_SIZE);
 
  Serial.println();
  Serial.println(F("注意,會把資料寫入到卡片 在 sector # "));
   
  Serial.println(F("Ready!"));
  Serial.println(F("==================================================="));
  Serial.println("Tap an RFID/NFC tag on the RFID-RC522 reader");
  // Connecting to an MQTT broker
  client.setServer(mqtt_broker, mqtt_port);
  client.setCallback(callback);

  while (!client.connected()) {
        String client_id = "esp32-client-";
        client_id += String(WiFi.macAddress());
        Serial.printf("The client %s connects to the public MQTT broker\n", client_id.c_str());
        if (client.connect(client_id.c_str(), mqtt_username, mqtt_password)) {
            Serial.println("Public HiveMQ MQTT broker (broker.mqtt-dashboard.com) connected");
        } else {
            Serial.print("Failed with state ");
            Serial.print(client.state());
            delay(2000);
        }
  }

  // MQTT Publish and subscribe
  client.subscribe(topic1);
  client.subscribe(topic2);
}
//===========================================================
void loop() {

  // 查看是否感應到卡片
  if ( ! mfrc522.PICC_IsNewCardPresent()) {
    return;  // 退回loop迴圈的開頭
  }

  // 選取一張卡片
  if ( ! mfrc522.PICC_ReadCardSerial()) {  // 若傳回1,代表已讀取到卡片的ID
    return;
  }

  if ((sector>0) ||(block>0)) {
    if (WR_flag==true){
      writeBlock(sector, block, blockData);  // 區段編號、區塊編號、包含寫入資料的陣列
      readBlock(sector, block, buffer);      // 區段編號、區塊編號、存放讀取資料的陣列
      Serial.print("sector=");
      Serial.print(sector,DEC);
      Serial.print(", block=");
      Serial.println(block,DEC);

      Serial.print(F("Read block: "));        // 顯示儲存讀取資料的陣列元素值
      for (byte i = 0 ; i < 16 ; i++) {
        Serial.write (buffer[i]);
      }
      Serial.println();
      //========publish topic3 =========
      String json ="Read data : ";
      String str=String((char *)buffer);
      json =json + str;
      json.trim();
      //json.toCharArray(jsonChar, json.length()+1);
      json.toCharArray(jsonChar,28+1);
      client.publish(topic3,jsonChar);

      WR_flag==false;
    }
   
   
    if (RD_flag==true){
      readBlock(sector, block, buffer);      // 區段編號、區塊編號、存放讀取資料的陣列
      Serial.print("sector=");
      Serial.print(sector,DEC);
      Serial.print(", block=");
      Serial.println(block,DEC);

      Serial.print(F("Read block: "));        // 顯示儲存讀取資料的陣列元素值
      for (byte i = 0 ; i <18 ; i++) {
        Serial.write (buffer[i]);
      }
      Serial.println();
      //========publish topic3 =========
      String json ="Read data : ";
      String str=String((char *)buffer);
      json =json + str;
      json.trim();
      //json.toCharArray(jsonChar, json.length()+1);
      json.toCharArray(jsonChar,28+1);
      client.publish(topic3,jsonChar);

      RD_flag==false;
    }

  }
  else
  {
    Serial.print(F("Card UID:"));
    dump_byte_array(mfrc522.uid.uidByte, mfrc522.uid.size); // 顯示卡片的UID
    Serial.println();
    Serial.print(F("PICC type: "));
    MFRC522::PICC_Type piccType = mfrc522.PICC_GetType(mfrc522.uid.sak);
    Serial.println(mfrc522.PICC_GetTypeName(piccType));  //顯示卡片的類型  
   
    String json =("Card UID: ");
    json = json + printHex(mfrc522.uid.uidByte, mfrc522.uid.size);
    json.trim();
    json = json +(" , PICC type: ");
    json = json + String(mfrc522.PICC_GetTypeName(piccType));
    json.trim();
    ///json.toUpperCase();
    // Convert JSON string to character array
    json.toCharArray(jsonChar, json.length()+1);
    client.publish(topic3,jsonChar);

    // Dump debug info about the card; PICC_HaltA() is automatically called
    mfrc522.PICC_DumpToSerial(&(mfrc522.uid));

  }

 

  // 令卡片進入停止狀態
  mfrc522.PICC_HaltA();
  mfrc522.PCD_StopCrypto1(); // stop encryption on PCD
  Serial.println("RFID Halt");


 if (!client.connected()) { //假設未連接的處理程序
      reconnect();
      Serial.print(" client not connected  reconnect ");
      delay(200);
    }
  client.loop();

// if WiFi is down, try reconnecting
  if (WiFi.status() != WL_CONNECTED) {
    Serial.print(millis());
    Serial.println("Reconnecting to WiFi...");
    WiFi.disconnect();
    WiFi.reconnect();
    client.setCallback(callback);

  }

}


load:0x3fff0030,len:1416

load:0x40078000,len:14804

load:0x40080400,len:4

load:0x40080404,len:3356

entry 0x4008059c


Connecting to dlink-103A

.

WiFi connected

IP address: 

192.168.0.100

Please scan MIFARE Classic card...

掃描卡片開始進行讀或者寫

使用A和B作為KEY FF FF FF FF FF FF

注意,會把資料寫入到卡片 在 sector # 

Ready!

===================================================

Tap an RFID/NFC tag on the RFID-RC522 reader

The client esp32-client-24:6F:28:A9:83:F4 connects to the public MQTT broker

Public HiveMQ MQTT broker (broker.mqtt-dashboard.com) connected

Card UID: 86 D5 EA 6A

PICC type: MIFARE 1KB

Card UID: 86 D5 EA 6A

Card SAK: 08

PICC type: MIFARE 1KB

Sector Block   0  1  2  3   4  5  6  7   8  9 10 11  12 13 14 15  AccessBits

  15     63   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ] 

         62   61 6C 65 78  39 75 66 6F  74 65 73 74  69 6E 67 35  [ 0 0 0 ] 

         61   61 6C 65 78  39 75 66 6F  74 65 73 74  69 6E 67 31  [ 0 0 0 ] 

         60   61 6C 65 78  39 75 66 6F  74 65 73 74  69 6E 67 35  [ 0 0 0 ] 


RFID Halt

Message arrived in topic: alex9ufo/RFID/read

Message: 05,01

0501

-------callback-----------

Data was read.

sector=5, block=1

Read block: alex9ufo testing:

RFID Halt

Data was read.

sector=5, block=1

Read block: alex9ufo testing:

RFID Halt



RFID Halt

Card UID: 86 D5 EA 6A

PICC type: MIFARE 1KB

Card UID: 86 D5 EA 6A

Card SAK: 08

PICC type: MIFARE 1KB

Sector Block   0  1  2  3   4  5  6  7   8  9 10 11  12 13 14 15  AccessBits

  15     63   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ]

         62   61 6C 65 78  39 75 66 6F  74 65 73 74  69 6E 67 35  [ 0 0 0 ]

         61   61 6C 65 78  39 75 66 6F  74 65 73 74  69 6E 67 31  [ 0 0 0 ]

         60   61 6C 65 78  39 75 66 6F  74 65 73 74  69 6E 67 35  [ 0 0 0 ]

  14     59   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ]

         58   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]

         57   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]

         56   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]

  13     55   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ]

         54   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]

         53   4B 65 65 70  20 48 61 63  6B 69 6E 67  21 00 00 00  [ 0 0 0 ]

         52   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]

  12     51   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ]

         50   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]

         49   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]

         48   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]

  11     47   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ]

         46   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]

         45   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]

         44   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]

  10     43   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ]

         42   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]

         41   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]

         40   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]

   9     39   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ]

         38   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]

         37   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]

         36   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]

   8     35   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ]

         34   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]

         33   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]

         32   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]

   7     31   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ]

         30   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]

         29   74 65 73 74  00 48 61 63  6B 69 6E 67  21 00 00 00  [ 0 0 0 ]

         28   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]

   6     27   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ]

         26   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]

         25   61 6C 65 78  39 75 66 6F  20 74 65 73  74 69 6E 67  [ 0 0 0 ]

         24   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]

   5     23   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ]

         22   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]

         21   61 6C 65 78  39 75 66 6F  20 74 65 73  74 69 6E 67  [ 0 0 0 ]

         20   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]

   4     19   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ]

         18   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]

         17   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]

         16   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]

   3     15   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ]

         14   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]

         13   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]

         12   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]

   2     11   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ]

         10   2B 39 32 33  30 30 34 34  34 37 37 37  37 20 20 20  [ 0 0 0 ]

          9   32 38 2D 30  39 2D 31 39  38 39 20 20  20 20 20 20  [ 0 0 0 ]

          8   4A 68 6F 6E  20 41 62 72  61 68 75 6D  20 20 20 20  [ 0 0 0 ]

   1      7   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ]

          6   41 6E 74 68  6F 6E 79 20  20 20 20 20  20 20 20 20  [ 0 0 0 ]

          5   20 20 20 20  20 20 20 20  20 20 20 20  20 20 00 00  [ 0 0 0 ]

          4   01 02 03 04  05 06 07 08  00 00 00 00  00 00 00 00  [ 0 0 0 ]

   0      3   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ]

          2   61 6C 65 78  39 75 66 6F  20 74 65 73  74 69 6E 67  [ 0 0 0 ]

          1   61 6C 65 78  20 20 20 20  20 20 20 20  20 20 20 20  [ 0 0 0 ]

          0   86 D5 EA 6A  D3 08 04 00  62 63 64 65  66 67 68 69  [ 0 0 0 ]


NODE-RED程式




[{"id":"440dc39decd59992","type":"function","z":"e0e6742e2f6dbb32","name":"function  ","func":"var arr = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];\nmsg.payload=arr;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":240,"y":220,"wires":[["4681174250f230f4","62eed776a0fae487"]]},{"id":"794846c8299b7423","type":"inject","z":"e0e6742e2f6dbb32","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":"1","topic":"","payload":"","payloadType":"date","x":100,"y":220,"wires":[["440dc39decd59992"]]},{"id":"4681174250f230f4","type":"debug","z":"e0e6742e2f6dbb32","name":"debug 251","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":410,"y":220,"wires":[]},{"id":"62eed776a0fae487","type":"change","z":"e0e6742e2f6dbb32","name":"","rules":[{"t":"set","p":"options","pt":"msg","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":410,"y":180,"wires":[["6970876a0912347f"]]},{"id":"6970876a0912347f","type":"ui_dropdown","z":"e0e6742e2f6dbb32","name":"","label":"SECTOR NO:","tooltip":"","place":"Select option","group":"4375a788bff1fee7","order":1,"width":5,"height":1,"passthru":true,"multiple":false,"options":[{"label":"","value":"","type":"str"}],"payload":"","topic":"topic","topicType":"msg","className":"","x":600,"y":180,"wires":[["76f618d8468c543c","a34c99c30f9124ac"]]},{"id":"76f618d8468c543c","type":"debug","z":"e0e6742e2f6dbb32","name":"debug 252","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":750,"y":240,"wires":[]},{"id":"173499103408be5a","type":"inject","z":"e0e6742e2f6dbb32","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":"1","topic":"","payload":"","payloadType":"date","x":100,"y":280,"wires":[["e7c1df4d5e779173"]]},{"id":"e7c1df4d5e779173","type":"function","z":"e0e6742e2f6dbb32","name":"function  ","func":"var arr = [0,1,2];\nmsg.payload=arr;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":240,"y":280,"wires":[["2081dfec848a4f66","1bf54f0df38a17f6"]]},{"id":"1bf54f0df38a17f6","type":"change","z":"e0e6742e2f6dbb32","name":"","rules":[{"t":"set","p":"options","pt":"msg","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":410,"y":320,"wires":[["fcdf176530f8f52b"]]},{"id":"2081dfec848a4f66","type":"debug","z":"e0e6742e2f6dbb32","name":"debug 253","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":410,"y":280,"wires":[]},{"id":"fcdf176530f8f52b","type":"ui_dropdown","z":"e0e6742e2f6dbb32","name":"","label":"BLOCK    NO:","tooltip":"","place":"Select option","group":"4375a788bff1fee7","order":3,"width":5,"height":1,"passthru":true,"multiple":false,"options":[{"label":"","value":"","type":"str"}],"payload":"","topic":"topic","topicType":"msg","className":"","x":590,"y":320,"wires":[["742b2a78cedc2748","9642693593b2476b"]]},{"id":"742b2a78cedc2748","type":"debug","z":"e0e6742e2f6dbb32","name":"debug 254","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":750,"y":380,"wires":[]},{"id":"94dea7d5330ef913","type":"ui_button","z":"e0e6742e2f6dbb32","name":"","group":"4375a788bff1fee7","order":5,"width":5,"height":1,"passthru":false,"label":"讀取","tooltip":"","color":"","bgcolor":"","className":"","icon":"","payload":"","payloadType":"str","topic":"topic","topicType":"msg","x":70,"y":20,"wires":[["5e02e64f7e0fe670"]]},{"id":"df0a4bb4d3ae8982","type":"ui_button","z":"e0e6742e2f6dbb32","name":"","group":"4375a788bff1fee7","order":7,"width":5,"height":1,"passthru":false,"label":"寫入","tooltip":"","color":"","bgcolor":"","className":"","icon":"","payload":"","payloadType":"str","topic":"topic","topicType":"msg","x":70,"y":80,"wires":[["4479867fd9ee6b5e"]]},{"id":"cd3d4b973f912055","type":"ui_text_input","z":"e0e6742e2f6dbb32","name":"","label":"寫入的字串","tooltip":"","group":"4375a788bff1fee7","order":8,"width":11,"height":1,"passthru":true,"mode":"text","delay":300,"topic":"topic","sendOnBlur":true,"className":"","topicType":"msg","x":90,"y":140,"wires":[["07075a7612c40bf4"]]},{"id":"a35a6bc7a0738026","type":"ui_text","z":"e0e6742e2f6dbb32","group":"4375a788bff1fee7","order":12,"width":11,"height":1,"name":"","label":"RFID讀取回來的字串","format":"{{msg.payload}}","layout":"row-spread","className":"","x":360,"y":480,"wires":[]},{"id":"5e02e64f7e0fe670","type":"function","z":"e0e6742e2f6dbb32","name":"function  ","func":"var par1 = context.global.sec_no ;\nvar par2 = context.global.blk_no ;\nif(par1<10)\n{\n   par1 = '0'+par1;\n}\nif(par2<10)\n{\n   par2 = '0'+par2;\n}\nvar par3= par1+','+par2;\n\nmsg.payload=par3;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":220,"y":20,"wires":[["63bbbc908a4787b8","15b3490a50a2ce6c"]]},{"id":"4479867fd9ee6b5e","type":"function","z":"e0e6742e2f6dbb32","name":"function  ","func":"var par1 = context.global.sec_no ;\nvar par2 = context.global.blk_no ;\nvar par3 = context.global.str;\n\nif(par1<10)\n{\n   par1 = '0'+par1;\n}\n\nif(par2<10)\n{\n   par2 = '0'+par2;\n}\n\nvar par4= par1+','+par2+','+par3;\n\nmsg.payload=par4;\nreturn msg;\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":220,"y":80,"wires":[["f9d0f0c553234d13","15b3490a50a2ce6c"]]},{"id":"07075a7612c40bf4","type":"function","z":"e0e6742e2f6dbb32","name":"function  ","func":"context.global.str=msg.payload;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":240,"y":140,"wires":[["df0a4bb4d3ae8982","b1113b320af0444b"]]},{"id":"a34c99c30f9124ac","type":"function","z":"e0e6742e2f6dbb32","name":"function  ","func":"context.global.sec_no=msg.payload;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":780,"y":180,"wires":[[]]},{"id":"9642693593b2476b","type":"function","z":"e0e6742e2f6dbb32","name":"function  ","func":"context.global.blk_no=msg.payload;\nreturn msg;\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":760,"y":320,"wires":[[]]},{"id":"63bbbc908a4787b8","type":"mqtt out","z":"e0e6742e2f6dbb32","name":"","topic":"alex9ufo/RFID/read","qos":"1","retain":"false","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"841df58d.ee5e98","x":570,"y":20,"wires":[]},{"id":"afa41963d4f07c3a","type":"mqtt in","z":"e0e6742e2f6dbb32","name":"","topic":"alex9ufo/RFID/back","qos":"1","datatype":"auto-detect","broker":"841df58d.ee5e98","nl":false,"rap":true,"rh":0,"inputs":0,"x":110,"y":480,"wires":[["a35a6bc7a0738026"]]},{"id":"f9d0f0c553234d13","type":"mqtt out","z":"e0e6742e2f6dbb32","name":"","topic":"alex9ufo/RFID/write","qos":"1","retain":"false","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"841df58d.ee5e98","x":570,"y":80,"wires":[]},{"id":"15b3490a50a2ce6c","type":"debug","z":"e0e6742e2f6dbb32","name":"debug 255","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":370,"y":60,"wires":[]},{"id":"a306b5667ef71d7a","type":"mqtt in","z":"e0e6742e2f6dbb32","name":"","topic":"alex9ufo/RFID/read","qos":"1","datatype":"auto-detect","broker":"841df58d.ee5e98","nl":false,"rap":true,"rh":0,"inputs":0,"x":110,"y":360,"wires":[["9b5a8a3ddd50ad7e"]]},{"id":"2958973746da924b","type":"mqtt in","z":"e0e6742e2f6dbb32","name":"","topic":"alex9ufo/RFID/write","qos":"1","datatype":"auto-detect","broker":"841df58d.ee5e98","nl":false,"rap":true,"rh":0,"inputs":0,"x":110,"y":400,"wires":[["9b5a8a3ddd50ad7e"]]},{"id":"9b5a8a3ddd50ad7e","type":"ui_text","z":"e0e6742e2f6dbb32","group":"4375a788bff1fee7","order":10,"width":11,"height":1,"name":"","label":"MQTT 發行的字串","format":"{{msg.payload}}","layout":"row-left","className":"","x":330,"y":380,"wires":[]},{"id":"b1113b320af0444b","type":"debug","z":"e0e6742e2f6dbb32","name":"debug 256","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":410,"y":140,"wires":[]},{"id":"4375a788bff1fee7","type":"ui_group","name":"READ/WRITE 1K","tab":"048debf3dd7e9641","order":3,"disp":true,"width":11,"collapse":false,"className":""},{"id":"841df58d.ee5e98","type":"mqtt-broker","name":"","broker":"broker.hivemq.com","port":"1883","clientid":"","autoConnect":true,"usetls":false,"compatmode":false,"protocolVersion":"4","keepalive":"15","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","birthMsg":{},"closeTopic":"","closePayload":"","closeMsg":{},"willTopic":"","willQos":"0","willPayload":"","willMsg":{},"userProps":"","sessionExpiry":""},{"id":"048debf3dd7e9641","type":"ui_tab","name":"2024 RFID ","icon":"dashboard","disabled":false,"hidden":false}]



沒有留言:

張貼留言

Messaging API作為替代方案

  LINE超好用功能要沒了!LINE Notify明年3月底終止服務,有什麼替代方案? LINE Notify將於2025年3月31日結束服務,官方建議改用Messaging API作為替代方案。 //CHANNEL_ACCESS_TOKEN = 'Messaging ...