#define TRUE 1 #define FALSE 0 // Konstanty RS485 #define BUS_ID_RS485 1 // nastavení sériové linky COM1 #define READ_FUNCTION 4 // read input registr #define WRITE_FUNCTION 6 // zapsání hodnoty do holding registru sensoru #define TX_BUFFER_TYPE 1 #define RX_BUFFER_TYPE 2 #define FIRST_MODBUS_ADDRESS 1 // výchozí první adresa pro enumeraci #define LAST_MODBUS_ADDRESS 21 // výchozí poslední adresa pro enumeraci #define WRITE_TIMEOUT 100 #define READ_TIMEOUT 100 #define ENUMERATION_TIMEOUT 50 #define MAX_REPEAT 10 // max deset opakování při erroru (timeout i crc) #define MAX_REPEAT_ENUMERATION 5 // Konstanty LoRa #define BUS_ID_LORA 6 // nastavení sériové linky COM6 #define LORA_READ_BUFFER_SIZE 100 // velikost bufferu pro příjem odpovědi po síti LoRa #define LORA_INTERVAL 60 // výchozí interval odesílání hodnot na server #define MESSAGE_INTERVAL 60000 // interval mezi jednotlivými pakety 60s #define DEVICE_EUI "BE7A00000000002E" #define DEVICE_ADDR "012CA42F" #define NWK_SESSION_KEY "EF1D2A6E184AF78F09056BC066907A9C" #define APP_SESSION_KEY "CB219F896F247CC448080CAF416CA398" #define APP_KEY "FB06843631629B5F9427367529265AA7" // Chybové hlášky #define NOT_MEASURED 0x80000001 #define NOT_MEASURED_TIMEOUT 0x80000002 #define NOT_MEASURED_CRC 0x80000003 #define OK 0x00000001 #define ERROR_VALUE 0x80000000 // Typy senzorů #define TYPE_HT 0x01 #define TYPE_MHT_22 0x04 // verze HW 2.2 #define TYPE_MHT_23 0x06 // verze HW 2.3 // Komunikace se serverem #define IP_DEFAULT_1 10 // výchozí IP pro odesílání dat na server #define IP_DEFAULT_2 208 #define IP_DEFAULT_3 253 #define IP_DEFAULT_4 203 #define DEFAULT_PORT 48005 #define IP_DOMAIN_STRING "moistureguard.marekm.cz" // DNS doména pro obdržení IP adresy serveru #define THIS_SDS_ID 7777 // identifikační číslo SDS pro ukládání dat na server #define SDS_IDENT 0x40 #define UDP_INTERVAL 5 // odesílání na server jednou za minutu // Šifrování #define CRYPTO_ALGORITHM_XTEA 0x10 // XTEA algorithm #define CRYPTO_ALGORITHM_AES 0x20 // AES algorithm unsigned int i; unsigned int iv1, iv2, iv3, iv4; unsigned int packetID, packetNumber; unsigned int TxCRCResult, RxCRCResult, RxCRCValue, CRCError; unsigned int length, sensorAddr, response; unsigned int sensorIndex, sensorCount, sensorType; unsigned int packetLength, start, dataLength; unsigned int UDPTimeStamp, LoraTimeStamp; unsigned int IP0, IP1, IP2, IP3; // Pole pro komunikaci po RS485 char txBuffer[100]; char rxBuffer[100]; unsigned int res[100]; unsigned int _res; // Pole pro ukládání naměřených hodnot ze senzorů char addrArray[264]; // min 264 kvůli zapisování do DataFlash char typeArray[264]; int tempArray[64]; // max 64 senzorů kvůli nedostatku paměti int humArray[64]; int moiArray[64]; int resiArrayHI[64]; // do unsigned int pole ve full-c se na jeden index vejde pouze 16 bitů -> je potřeba 32 bitovou hodnotu rozdělit do dvou indexů int resiArrayLO[64]; int temp2Array[64]; int hum2Array[64]; // Proměnné pro komunikaci s webovou stránkou unsigned int U00; // restart programu unsigned int U01; // počet Modbus adres, se kterými se komunikuje unsigned int U02; // zahájení enumerace unsigned int U03; // první modbus adresa pro enumeraci unsigned int U04; // poslední modbus adresa pro enumeraci unsigned int U05; // stav enumerace unsigned int U06; // uložení dat do DataFlash unsigned int U07; // vymazání dat z DataFlash unsigned int U08; // posílání přes Ethernet on/off unsigned int U09; // šifrování dat při posílání přes Ethernet on/off unsigned int U10; // posílání přes LoRu on/off unsigned int U11; // odesílání LoRa paketů unsigned int U12; // UDP interval unsigned int U13; // LoRa interval char T00[64]; // adresy senzorů char T01[64]; // typy senzorů char T02[128]; // teploty char T03[128]; // vlhkosti char T04[128]; // vlhkosti materiálu char T05[256]; // odpory char T06[128]; // teploty 2 char T07[128]; // vlhkosti 2 // Proměnné pro práci s Data Flash char settings[264]; // pole pro uložení nastavení unsigned int firstModbusAddress, lastModbusAddress; // LoRa proměnné unsigned int loraStatus; char _crlf[]="\r\n"; char _answer[100]; char _answer6[6]; int LoRapwr; // Pole pro odesální na server char udpBuffer[295]; // max 64 Modbus adres * 4 + 23 nezašiforvaná část + 16 zašifrovaná část // ======================================================================== // // Modbus komunikace // ======================================================================== // // Provede CRC výpočet z dat obsažených v polích txBuffer nebo res. int countCRC(int length, int bufferType) { int crc = 0xffff; int index = 0; for(int i = 0; i < length; i++) { index = i; if (bufferType == TX_BUFFER_TYPE) { crc ^= txBuffer[index] & 0xff; } else { crc ^= res[index] & 0xff; } for(int j = 8; j != 0; j--) { if((crc & 0x0001) !=0) { crc = crc >> 1; crc ^= 0xa001; } else { crc = crc >> 1; } } } return crc & 0xffff; } // Spočítá CRC pro odesílací buffer void TxCRC() { TxCRCResult = countCRC(length, TX_BUFFER_TYPE); txBuffer[length] = TxCRCResult & 0xff; txBuffer[length + 1] = (TxCRCResult >> 8) & 0xff; } // Spočítá CRC pro přijímací buffer void RxCRC() { RxCRCResult = countCRC(length, RX_BUFFER_TYPE); int a = RxCRCResult & 0xff; int b = (RxCRCResult >> 8) & 0xff; if (res[length] == a && res[length + 1] == b) { CRCError = FALSE; } else { CRCError = TRUE; } } void sendFunction(int sensorAddr, int functionCode, int startAddr, int registerCount) { int i = 0; txBuffer[i] = sensorAddr; i++; txBuffer[i] = functionCode; i++; txBuffer[i] = (startAddr >> 8) & 0xff; i++; txBuffer[i] = startAddr & 0xff; i++; txBuffer[i] = (registerCount >> 8) & 0xff; i++; txBuffer[i] = registerCount & 0xff; i++; length = i; TxCRC(); length += 2; } // maxRepeat = maximální počet pokusů o přijetí dat po RS485. int readData(int maxRepeat) { unsigned int rss = 0; unsigned int retval = 0; unsigned int pru = 0; _res = 0; while (1) { rss = SDS_serial_read(1, rxBuffer, 100); if (pru < maxRepeat && rss == 0 && retval == 0) { // pru = počet pokusů wait(READ_TIMEOUT); pru++; } else { if (rss == 0) { break; } retval += rss; pru = 0; for(int i = 0; i < rss; i++) { res[_res] = rxBuffer[i]; _res++; } } } if (retval == 0) { return 0; } length = retval - 2; RxCRC(); length += 2; return retval; } // registerCount = počet vyčítaných registrů v závislost na typu senzoru. int readValues(int registerCount) { sendFunction(sensorAddr, READ_FUNCTION, 0, registerCount); SDS_serial_write(BUS_ID_RS485, txBuffer, length); wait(WRITE_TIMEOUT); response = readData(MAX_REPEAT); if (response > 0) { if (CRCError == FALSE) { printf("Received data from sensor address %d successfully!\n", sensorAddr); return TRUE; } else { printf("Error reading data from sensor address %d - CRC error\n", sensorAddr); return FALSE; } } else { printf("No data received from sensor address %d - Timeout error\n", sensorAddr); return FALSE; } } // Naplní příslušná pole naměřenými hodnotami ze senzorů. void readSensors() { if(sensorCount == 0) { printf("No sensors connected...\n"); break; } for(int i = 0; i < sensorCount; i++) { sensorAddr = addrArray[i]; if(typeArray[i] == TYPE_HT) { printf("Reading sensor address %d, sensor type %d...\n", sensorAddr, TYPE_HT); if (readValues(3) == 0) { // register count 3 tempArray[i] = 0; humArray[i] = 0; moiArray[i] = 0; resiArrayHI[i] = 0; resiArrayLO[i] = 0; temp2Array[i] = 0; hum2Array[i] = 0; } else { tempArray[i] = ((res[3] << 8) | res[4]); humArray[i] = ((res[5] << 8) | res[6]); moiArray[i] = 0; resiArrayHI[i] = 0; resiArrayLO[i] = 0; temp2Array[i] = 0; hum2Array[i] = 0; } } if(typeArray[i] == TYPE_MHT_22) { printf("Reading sensor address %d, sensor type %d...\n", sensorAddr, TYPE_MHT_22); if (readValues(6) == 0) { // register count 6 tempArray[i] = 0; humArray[i] = 0; moiArray[i] = 0; resiArrayHI[i] = 0; resiArrayLO[i] = 0; temp2Array[i] = 0; hum2Array[i] = 0; } else { tempArray[i] = ((res[3] << 8) | res[4]); humArray[i] = ((res[5] << 8) | res[6]); moiArray[i] = ((res[9] << 8) | res[10]); resiArrayHI[i] = ((res[11] << 8) | res[12]); resiArrayLO[i] = ((res[13] << 8) | res[14]); temp2Array[i] = 0; hum2Array[i] = 0; } } if(typeArray[i] == TYPE_MHT_23) { printf("Reading sensor address %d, sensor type %d...\n", sensorAddr, TYPE_MHT_23); if (readValues(12) == 0) { // register count 12 tempArray[i] = 0; humArray[i] = 0; moiArray[i] = 0; resiArrayHI[i] = 0; resiArrayLO[i] = 0; temp2Array[i] = 0; hum2Array[i] = 0; } else { tempArray[i] = ((res[3] << 8) | res[4]); humArray[i] = ((res[5] << 8) | res[6]); moiArray[i] = ((res[9] << 8) | res[10]); resiArrayHI[i] = ((res[11] << 8) | res[12]); resiArrayLO[i] = ((res[13] << 8) | res[14]); temp2Array[i] = ((res[23] << 8) | res[24]); hum2Array[i] = ((res[25] << 8) | res[26]); } } } } // ======================================================================== // // Enumeration // ======================================================================== // // Provede enumeraci v rozsahu U03 - U04. void enumeration() { printf("Starting enumeration in range %d - %d\n", U03, U04); unsigned int j = 0; U05 = TRUE; memset(&addrArray, 0, 264); memset(&typeArray, 0, 264); memset(&tempArray, 0, 64); // max 64 senzorů kvůli nedostatku paměti memset(&humArray, 0, 64); memset(&moiArray, 0, 64); memset(&resiArrayHI, 0, 64); // do unsigned int pole ve full-c se na jeden index vejde pouze 16 bitů -> je potřeba 32 bitovou hodnotu rozdělit do dvou indexů memset(&resiArrayLO, 0, 64); memset(&temp2Array, 0, 64); memset(&hum2Array, 0, 64); memset(&T00, 0, 64); memset(&T01, 0, 64); memset(&T02, 0, 128); memset(&T03, 0, 128); memset(&T04, 0, 128); memset(&T05, 0, 256); memset(&T06, 0, 128); memset(&T07, 0, 128); for (sensorAddr = U03; sensorAddr <= U04; sensorAddr++) { if (readSensorType() == TRUE) { addrArray[j] = sensorAddr; typeArray[j] = sensorType; j++; } } printf("Detected sensor addresses:\n"); for(int i = 0; i < j; i++) { printf("%d | ", addrArray[i]); } printf("\n"); for(int i = 0; i < j; i++) { printf("%d | ", typeArray[i]); } printf("\n"); sensorCount = strlen(&addrArray); U01 = sensorCount; U05 = FALSE; printf("\n"); printf("Enumeration DONE!\n"); printf("Total Sensor Count = %d\n", sensorCount); } int readSensorType() { sendFunction(sensorAddr, READ_FUNCTION, 3000, 1); SDS_serial_write(BUS_ID_RS485, txBuffer, length); wait(WRITE_TIMEOUT); response = readData(MAX_REPEAT_ENUMERATION); if (response > 0) { if (CRCError == FALSE) { sensorType = (res[3] << 8) | (res[4]); printf("Received data from sensor address %d successfully!\n", sensorAddr); return TRUE; } else { printf("Error reading sensor type address %d - CRC error\n", sensorAddr); return FALSE; } } else { printf("No data received from sensor address %d - Timeout error\n", sensorAddr); return FALSE; } } // ======================================================================== // // DataFlash // ======================================================================== // void saveToFlash() { unsigned int pageIndex = 0; printf("Saving data to flash...\n"); if (DF_write_page(pageIndex, &addrArray) == 1) { pageIndex = 1; if (DF_write_page(pageIndex, &typeArray) == 1) { pageIndex = 2; settings[0] = U03; settings[1] = U04; settings[2] = U08; settings[3] = U09; settings[4] = U10; settings[5] = U12; settings[6] = U13; if (DF_write_page(pageIndex, &settings) == 1) { printf("Data saved to flash successfully!\n"); } } } else { printf("Error saving data to flash.\n"); } } void loadFromFlash() { unsigned int pageIndex = 0; printf("Loading data from flash...:\n"); if (DF_read_page(pageIndex, &addrArray) == 0) { printf("Error loading data from flash.\n"); return; } pageIndex = 1; if (DF_read_page(pageIndex, &typeArray) == 0) { printf("Error loading data from flash.\n"); return; } pageIndex = 2; if (DF_read_page(pageIndex, &settings) == 0) { printf("Error loading data from flash.\n"); return; } if (strlen(&settings) == 264) { printf("Data flash is empty - setting default enumeration range %d - %d\n", FIRST_MODBUS_ADDRESS, LAST_MODBUS_ADDRESS); U01 = 0; U03 = FIRST_MODBUS_ADDRESS; U04 = LAST_MODBUS_ADDRESS; U08 = FALSE; // šifrování defaultně vypnuto U09 = FALSE; // odesílání na server defaultně vypnuto U10 = FALSE; // posílání přes LoRu U12 = UDP_INTERVAL; U13 = LORA_INTERVAL; enumeration(); } else { sensorCount = strlen(&addrArray); printf("Data from flash loaded succesfully!\n"); printf("Loaded sensor adresses: "); for (int i = 0; i < sensorCount; i++) { printf("%d | ", addrArray[i]); } printf("\n"); printf("Loaded sensor types: "); for (int i = 0; i < sensorCount; i++) { printf("%d | ", typeArray[i]); } printf("\n"); U01 = sensorCount; printf("Sensor count is: %d\n", sensorCount); U03 = settings[0]; U04 = settings[1]; U08 = settings[2]; U09 = settings[3]; U10 = settings[4]; U12 = settings[5]; U13 = settings[6]; printf("Enumeration range is: %d - %d\n", U03, U04); printf("UDP packet interval is: %d\n", U12); printf("LoRa packet interval is: %d\n", U13); } } void deleteFlash() { unsigned int pageIndex = 0; if (DF_erase_page(pageIndex) == 1) { pageIndex = 1; if (DF_erase_page(pageIndex) == 1) { pageIndex = 2; if (DF_erase_page(pageIndex) == 1) { printf("Data from flash deleted successfully!\n"); } } } else { printf("Error deleting data from flash.\n"); } } // ======================================================================== // // User Web Page // ======================================================================== // // Naplní pole T00 až T07 hodnotami z polí s naměřenými hodnotami. void sendDataToWebPage() { int index = 0; for (int i = 0; i < sensorCount; i++) { if (i < sensorCount - 1) { index += snprintf(&T00[index], 3, "%d,", addrArray[i]) - 1; } else { index += snprintf(&T00[index], 3, "%d", addrArray[i]) - 1; } } index = 0; for (int i = 0; i < sensorCount; i++) { if (i < sensorCount - 1) { index += snprintf(&T01[index], 3, "%d,", typeArray[i]) - 1; } else { index += snprintf(&T01[index], 3, "%d", typeArray[i]) - 1; } } index = 0; for (int i = 0; i < sensorCount; i++) { if (i < sensorCount - 1) { index += snprintf(&T02[index], 5, "%d,", tempArray[i]) - 1; } else { index += snprintf(&T02[index], 5, "%d", tempArray[i]) - 1; } } index = 0; for (int i = 0; i < sensorCount; i++) { if (i < sensorCount - 1) { index += snprintf(&T03[index], 5, "%d,", humArray[i]) - 1; } else { index += snprintf(&T03[index], 5, "%d", humArray[i]) - 1; } } index = 0; for (int i = 0; i < sensorCount; i++) { if (i < sensorCount - 1) { index += snprintf(&T04[index], 5, "%d,", moiArray[i]) - 1; } else { index += snprintf(&T04[index], 5, "%d", moiArray[i]) - 1; } } index = 0; for (int i = 0; i < sensorCount; i++) { if (i < sensorCount - 1) { index += snprintf(&T05[index], 10, "%d,", (resiArrayHI[i] << 16) | resiArrayLO[i]) - 1; } else { index += snprintf(&T05[index], 10, "%d", (resiArrayHI[i] << 16) | resiArrayLO[i]) - 1; } } index = 0; for (int i = 0; i < sensorCount; i++) { if (i < sensorCount - 1) { index += snprintf(&T06[index], 5, "%d,", temp2Array[i]) - 1; } else { index += snprintf(&T06[index], 5, "%d", temp2Array[i]) - 1; } } index = 0; for (int i = 0; i < sensorCount; i++) { if (i < sensorCount - 1) { index += snprintf(&T07[index], 5, "%d,", hum2Array[i]) - 1; } else { index += snprintf(&T07[index], 5, "%d", hum2Array[i]) - 1; } } index = 0; } // ======================================================================== // // Komunikace přes rozhraní Ethernet // ======================================================================== // // start označuje index celkové zprávy (8 paketů), od kterého se mají na serveru začít ukládat data z aktuálně přenášeného paketu void createPacket(int start) { i = 0; iv1 = rand() & 0xffffffff; // dám si random 32 bitů do každé proměnné iv2 = rand() & 0xffffffff; iv3 = rand() & 0xffffffff; iv4 = rand() & 0xffffffff; udpBuffer[i] = (THIS_SDS_ID >> 24) & 0xff; i++; // první 4 bajty jsou SDS ID udpBuffer[i] = (THIS_SDS_ID >> 16) & 0xff; i++; udpBuffer[i] = (THIS_SDS_ID >> 8) & 0xff; i++; udpBuffer[i] = THIS_SDS_ID & 0xff; i++; udpBuffer[i] = SDS_IDENT; i++; // další bajt je SDS ident (?) udpBuffer[i] = (iv1 >> 24) & 0xff; i++; // první random 4 bajtové číslo udpBuffer[i] = (iv1 >> 16) & 0xff; i++; udpBuffer[i] = (iv1 >> 8) & 0xff; i++; udpBuffer[i] = iv1 & 0xff; i++; udpBuffer[i] = (iv2 >> 24) & 0xff; i++; // druhé random 4 bajtové číslo udpBuffer[i] = (iv2 >> 16) & 0xff; i++; udpBuffer[i] = (iv2 >> 8) & 0xff; i++; udpBuffer[i] = iv2 & 0xff; i++; udpBuffer[i] = (iv3 >> 24) & 0xff; i++; // třetí random 4 bajtové číslo udpBuffer[i] = (iv3 >> 16) & 0xff; i++; udpBuffer[i] = (iv3 >> 8) & 0xff; i++; udpBuffer[i] = iv3 & 0xff; i++; udpBuffer[i] = (iv4 >> 24) & 0xff; i++; // čtvrté random 4 bajtové číslo udpBuffer[i] = (iv4 >> 16) & 0xff; i++; udpBuffer[i] = (iv4 >> 8) & 0xff; i++; udpBuffer[i] = iv4 & 0xff; i++; udpBuffer[i] = (packetLength >> 8) & 0xff; i++; // sem přijde délka zašivrované části 2B udpBuffer[i] = packetLength & 0xff; i++; udpBuffer[i] = 0x00; i++; // zde začíná zašifrovaná část - čas odeslání UNIX čas 4B udpBuffer[i] = 0x00; i++; udpBuffer[i] = 0x00; i++; udpBuffer[i] = 0x00; i++; udpBuffer[i] = (start >> 8) & 0xff; i++; // start udpBuffer[i] = start & 0xff; i++; udpBuffer[i] = (dataLength >> 8) & 0xff; i++; // počet přenášených 4 bajtových slov v konkrétním paketu udpBuffer[i] = dataLength & 0xff; i++; udpBuffer[i] = (packetID >> 8) & 0xff; i++; // pořadové číslo paketu, neustále narůstá (paket ID) udpBuffer[i] = packetID & 0xff; i++; udpBuffer[i] = (packetNumber >> 8) & 0xff; i++; // číslo paketu udpBuffer[i] = packetNumber & 0xff; i++; udpBuffer[i] = 0x00; i++; udpBuffer[i] = 0x08; i++; // přenáší se 8 paketů patřících k sobě packetNumber++; } // Přída na konec UDP paketu výsledek kontrolního součtu všech hodnot nezašifrovaných dat. void checkSum() { unsigned int sum; for (int j = 23; j < i; j++) { sum += udpBuffer[j]; } printf("Check sum = %d\n", sum); udpBuffer[i] = (sum >> 8) & 0xff; i++; udpBuffer[i] = sum & 0xff; } void sendSensorAddrToServer() { start = 0; dataLength = ((sensorCount + 3) / 4) * 4; createPacket(start); for (int j = 0; j < dataLength; j++) { udpBuffer[i] = (addrArray[j] >> 24) & 0xff; i++; udpBuffer[i] = (addrArray[j] >> 16) & 0xff; i++; udpBuffer[i] = (addrArray[j] >> 8) & 0xff; i++; udpBuffer[i] = addrArray[j] & 0xff; i++; } checkSum(); printUDPBuffer(); encrypt(); sendUDPPacket(); } void sendSensorTypeToServer() { start = ((4 * sensorCount + 15) / 16) * 16; createPacket(start); for (int j = 0; j < dataLength; j++) { udpBuffer[i] = (typeArray[j] >> 24) & 0xff; i++; udpBuffer[i] = (typeArray[j] >> 16) & 0xff; i++; udpBuffer[i] = (typeArray[j] >> 8) & 0xff; i++; udpBuffer[i] = typeArray[j] & 0xff; i++; } checkSum(); printUDPBuffer(); encrypt(); sendUDPPacket(); } void sendTemperatureToServer() { createPacket(start * 2); for (int j = 0; j < dataLength; j++) { udpBuffer[i] = (tempArray[j] >> 24) & 0xff; i++; udpBuffer[i] = (tempArray[j] >> 16) & 0xff; i++; udpBuffer[i] = (tempArray[j] >> 8) & 0xff; i++; udpBuffer[i] = tempArray[j] & 0xff; i++; } checkSum(); printUDPBuffer(); encrypt(); sendUDPPacket(); } void sendHumidityToServer() { createPacket(start * 3); for (int j = 0; j < dataLength; j++) { udpBuffer[i] = (humArray[j] >> 24) & 0xff; i++; udpBuffer[i] = (humArray[j] >> 16) & 0xff; i++; udpBuffer[i] = (humArray[j] >> 8) & 0xff; i++; udpBuffer[i] = humArray[j] & 0xff; i++; } checkSum(); printUDPBuffer(); encrypt(); sendUDPPacket(); } void sendMoistureToServer() { createPacket(start * 4); for (int j = 0; j < dataLength; j++) { udpBuffer[i] = (moiArray[j] >> 24) & 0xff; i++; udpBuffer[i] = (moiArray[j] >> 16) & 0xff; i++; udpBuffer[i] = (moiArray[j] >> 8) & 0xff; i++; udpBuffer[i] = moiArray[j] & 0xff; i++; } checkSum(); printUDPBuffer(); encrypt(); sendUDPPacket(); } void sendResistanceToServer() { createPacket(start * 5); for (int j = 0; j < dataLength; j++) { udpBuffer[i] = (resiArrayHI[j] >> 8) & 0xff; i++; udpBuffer[i] = resiArrayHI[j] & 0xff; i++; udpBuffer[i] = (resiArrayLO[j] >> 8) & 0xff; i++; udpBuffer[i] = resiArrayLO[j] & 0xff; i++; } checkSum(); printUDPBuffer(); encrypt(); sendUDPPacket(); } void sendTemperature2ToServer() { createPacket(start * 6); for (int j = 0; j < dataLength; j++) { udpBuffer[i] = (temp2Array[j] >> 24) & 0xff; i++; udpBuffer[i] = (temp2Array[j] >> 16) & 0xff; i++; udpBuffer[i] = (temp2Array[j] >> 8) & 0xff; i++; udpBuffer[i] = temp2Array[j] & 0xff; i++; } checkSum(); printUDPBuffer(); encrypt(); sendUDPPacket(); } void sendHumidity2ToServer() { createPacket(start * 7); for (int j = 0; j < dataLength; j++) { udpBuffer[i] = (hum2Array[j] >> 24) & 0xff; i++; udpBuffer[i] = (hum2Array[j] >> 16) & 0xff; i++; udpBuffer[i] = (hum2Array[j] >> 8) & 0xff; i++; udpBuffer[i] = hum2Array[j] & 0xff; i++; } checkSum(); printUDPBuffer(); encrypt(); sendUDPPacket(); } void printUDPBuffer() { for(int z = 0; z < i; z++) { if(z == 23) { printf("; | "); } printf("%02x | ", udpBuffer[z]); } printf("\n"); } void encrypt() { if (U09 == FALSE) { printf("Encryption not enabled.\n"); return; } else { printf("Encrypting...\n"); unsigned int inputLength = dataLength * 4 + 16; unsigned int IV[4]; unsigned int ret; printf("Input length = %d\n", inputLength); char *buf; buf = (char*) malloc(inputLength + 1); printf("Plain-text input:\n"); for (int i = 0; i < inputLength; i++) { buf[i] = udpBuffer[i + 23]; printf("%02x | ", buf[i]); } IV[0] = iv1; // IV part-32bit IV[1] = iv2; // IV part-32bit IV[2] = iv3; // IV part-32bit IV[3] = iv4; // IV part-32bit ret = SDS_crypto(CRYPTO_ALGORITHM_AES, (void *)&IV, (void *)buf, inputLength); printf("\nEncrypt ret-val = %d\n", ret); printf("Encrypted text:\n"); for (int i = 0; i < inputLength; i++) { printf("%02x | ", buf[i]); } printf("\n"); IV[0] = iv1; // IV part-32bit IV[1] = iv2; // IV part-32bit IV[2] = iv3; // IV part-32bit IV[3] = iv4; // IV part-32bit /* Rozšifrování zprávy ret = SDS_crypto(CRYPTO_ALGORITHM_AES, (void *)&IV, (void *)buf, inputLength); // debug printf("Decrypt ret-val = %d\n", ret); printf("Decrypt text: \n"); for (i = 0; i < inputLength; i++) { printf("%02x | ", buf[i]); } */ printf("\n"); free(buf); } } void sendUDPPacket() { printf("Sending UDP packet...\n"); udp_send(IP_DEFAULT_1, IP_DEFAULT_2, IP_DEFAULT_3, IP_DEFAULT_4, DEFAULT_PORT, (void *)udpBuffer, i); int status = udp_send_status(); while (status == 1) { status = udp_send_status(); } if (status == 2) { printf("Sending DONE\n"); } else { printf("ERROR: %d\n", status); } } void sendToServer() { packetLength = 16 + ((4 * sensorCount + 15) / 16) * 16; // 14B informace o paketu, 2B checksum, N*4B data -> délka zašifrované části, délka musí být dělitelná 16 kvůli Payload AES packetNumber = 1; sendSensorAddrToServer(); sendSensorTypeToServer(); sendTemperatureToServer(); sendHumidityToServer(); sendMoistureToServer(); sendResistanceToServer(); sendTemperature2ToServer(); sendHumidity2ToServer(); packetID++; } int waitForIP() { for (int i = 0; i < 5; i++) { U08 = 2; if (SDS_get_u(27) == 1) { printf("IP address loaded.\n"); U08 = 1; return TRUE; } else { printf("Waiting for IP address from DHCP.\n"); wait(1000); } } return FALSE; } // SDS-BIG nezbývá dostatek pamět pro zavolání těchto funkcí, funguje pouze když odstraním všechna int pole pro ukládání hodnot ze senzorů (int tempArray atd.) /* void getServerIP() { unsigned int status; printf("Resolving %s\n", IP_DOMAIN_STRING); dns_resolv(IP_DOMAIN_STRING); status = dns_resolv_status(&IP0, &IP1, &IP2, &IP3); while (status == 512) { // dotaz byl odeslán, čekejte status = dns_resolv_status(&IP0, &IP1, &IP2, &IP3); } if (status == 513) { // dotaz byl odeslán, čekejte status = dns_resolv_status(&IP0, &IP1, &IP2, &IP3); printf("Received IP address: %u.%u.%u.%u\n", IP0, IP1, IP2, IP3); } else { printf("DNS resolv failed (error %u).\n", status); } } void getResponseFromServer() { unsigned int status; unsigned char * receiveDataBuffer; unsigned int httpResponseValue; unsigned int receivedDataSize; receiveDataBuffer = (unsigned char *)malloc(128); if (receiveDataBuffer == 0) { printf("Out of memory\n"); return; } printf("Calling http get...\n"); http_get(IP0, IP1, IP2, IP3, 61002, IP_DOMAIN_STRING, "?sdsId=1003&action=getPeriod", (void *)receiveDataBuffer, 128); status = http_get_status(&httpResponseValue, &receivedDataSize); while (status == 1023) { status = http_get_status(&httpResponseValue, &receivedDataSize); } if (status == 1024) { printf("OK. Response value: %u Received data size: %u\n", httpResponseValue, receivedDataSize); if (receivedDataSize > 0) { printf("Server response: %s\n\n\n\n", (char *)receiveDataBuffer); } } else { printf("FAILED. Error code = %u\n\n\n\n", status); } free(receiveDataBuffer); } */ // ======================================================================== // // LoRa komunikace // ======================================================================== // // Odešle adresy nebo typy senzorů po síti LoRa. void sendAddrLora(char * array) { int index = 0; char * buf; buf = (char*) malloc(sensorCount); memset((void*)buf, 0, sensorCount); for (int i = 0; i < sensorCount; i++) { index += snprintf(&buf[index], 3, "%02x", array[i]) - 1; } sendLoraMessage(buf); free(buf); } // Odešle naměřené hodnoty po síti LoRa. void sendValuesLora(int * array) { int index = 0; char * buf; buf = (char *)malloc(sensorCount * 4); memset((void*)buf, 0, sensorCount * 4); for (int i = 0; i < sensorCount; i++) { index += snprintf(&buf[index], 5, "%04x", array[i]) - 1; } sendLoraMessage(buf); free(buf); } // Připraví buffer pro odeslání dat, data jsou předána v parametru message. Vyhodnotí odpověď přijatou od LoRa modulu. void sendLoraMessage(char * message) { printf("LoRa - Zpráva se odesílá...\n"); unsigned int _rs=0; char *_payload; _payload = (char *)malloc(200); memset((void *)_payload, 0, 200); char *_conv; _conv = (char *)malloc(200); memset((void *)_conv, 0, 200); printf("Odesílají se data '%s'\n", message); strcat(_payload, message); sprintf(_conv, "mac tx uncnf 1 "); strcat(_conv, _payload); strcat(_conv, _crlf); senddataLora(_conv); free(_conv); _conv = 0; free(_payload); _payload = 0; _rs = 0; _rs = readdataLora(); if (_rs == 0) { printf("Chyba provedení příkazu mac tx uncnf 1 (payload)\n"); return; } //kontrola na spravne odeslani prikazu //OK\r\n je hned po odeslani prikazu if (strcmp(_answer, "ok\r\n") == 0){ //mac_tx_ok\r\n je po dokonceni komunikace unsigned int _pru; for (_pru = 0; _pru < 10; _pru++) { printf("Čekám na potvrzení přijetí dat (%u/10)\n", _pru); wait(1000); _rs=0; readdataLora(); strncpy(_answer6, _answer, 6); if ((strcmp(_answer, "mac_tx_ok\r\n") == 0) || (strcmp(_answer6, "mac_rx") == 0)) { printf("Data odeslána\n"); break; } else if (strcmp(_answer, "no_free_ch\r\n") == 0) { printf("Není volný kanál pro odeslání dat. Čekám 1min a opakuji příkaz.\n"); wait(50000); //50s + dole je 10s prodleva na zpracovani zpravy break; } else { if (_rs>0) { printf("Chyba potvrzení přijetí dat (%u)%s\n", _rs, _answer); } } } } else if (strcmp(_answer, "no_free_ch\r\n") == 0) { printf("Není volný kanál pro odeslání dat. Čekám 1min a opakuji příkaz.\n"); wait(50000); //50s + dole je 10s prodleva na zpracovani zpravy } else { printf("Odpověď (chyba) na TX %s", _answer); } } // Provede nastavení klíču a připojení do sítě LoRa. void factoryreset() { printf("Provádí se factory reset\n"); senddataLora("sys factoryRESET\r\n"); if (readdataLora() == 0) { printf("Chyba provedení příkazu sys factoryRESET\n"); //printf("Chyba provedení příkazu sys reset\n"); return; } //set device EUI char _data[50] = "mac set deveui "; //+mezera strcat(_data, DEVICE_EUI); strcat(_data, _crlf); senddataLora(_data); if (readdataLora() == 0) { printf("Chyba provedení příkazu mac set deveui\n"); return; } //set device addres char _data[50] = "mac set devaddr "; //+mezera strcat(_data, DEVICE_ADDR); strcat(_data, _crlf); senddataLora(_data); if (readdataLora() == 0) { printf("Chyba provedení příkazu mac set devaddr\n"); return; } //set network session key char _data[50] = "mac set nwkskey "; //+mezera strcat(_data, NWK_SESSION_KEY); strcat(_data, _crlf); senddataLora(_data); if (readdataLora() == 0) { printf("Chyba provedení příkazu mac set nwkskey\n"); return; } //set application session key char _data[50] = "mac set appskey "; //+mezera strcat(_data, APP_SESSION_KEY); strcat(_data, _crlf); senddataLora(_data); if (readdataLora() == 0) { printf("Chyba provedení příkazu mac set appskey\n"); return; } //set application key char _data[50] = "mac set appkey "; //+mezera strcat(_data, APP_KEY); strcat(_data, _crlf); senddataLora(_data); if (readdataLora() == 0) { printf("Chyba provedení příkazu mac set appkey\n"); return; } //set retransmissions for uplink confirmed packet senddataLora("mac set retx 7\r\n"); if (readdataLora() == 0) { printf("Chyba provedení příkazu mac set retx\n"); return; } //zapnout Adaptive Data Rate senddataLora("mac set adr on\r\n"); if (readdataLora() == 0) { printf("Chyba provedení příkazu mac set adr on\n"); return; } //save config senddataLora("mac save\r\n"); if (readdataLora() == 0) { printf("Chyba provedení příkazu mac save\n"); return; } printf("Factory reset a nové nastavení uloženo\n"); } // sets the transmitter output power void setOutputPower(int pwr) { int rs=0; printf("Nastavuji Tx output power...\n"); //char data[50] = "radio set pwr "; char data[50] = "mac set pwridx "; char var[5]; sprintf(var, "%d\r\n", pwr); strcat(data, var); senddataLora(data); rs = 0; rs = readdataLora(); if (rs == 0) { printf("Chyba provedení příkazu radio set pwr\n"); } } // gets the transmitter output power int getOutputPower() { //char data[50] = "radio get pwr\r\n"; char data[50] = "mac get pwridx\r\n"; int rs=0; senddataLora(data); rs = 0; rs = readdataLora(); if (rs == 0) { printf("Chyba provedení příkazu radio get pwr\n"); return -10; // N/A value } return atoi(_answer); } // Odešle data předaná v paramteru write po síti LoRa. void senddataLora(char * write) { unsigned int _len; _len = strlen(write); if (_len < 1) { printf("Prázdný příkaz\n"); return; } printf("Odesílám příkaz %s", write); SDS_serial_write(BUS_ID_LORA, (void *)write, _len); wait(500); //pockam na odpoved 500ms } // Naplní pole _answer odpovědí od LoRa modulu. int readdataLora() { char *readBuf; readBuf = (char *)malloc(LORA_READ_BUFFER_SIZE); memset((void *)readBuf, 0, LORA_READ_BUFFER_SIZE); unsigned int _rs=0; unsigned int _retval=0; unsigned int _pru=0; while (1) { _rs = SDS_serial_read(BUS_ID_LORA, (void *)readBuf, LORA_READ_BUFFER_SIZE); //pokud nic nedostanu, dam mu jeste sanci if (_pru<=5 && _rs == 0 && _retval == 0) { wait(500); _pru++; } else { if (_rs == 0) { printf("No response from LoRa...\n"); break; } _retval+=_rs; _pru=0; printf("Odpověď: (délka %u) %s", _rs, readBuf); } } _answer = readBuf; //global free(readBuf); return _retval; } // ======================================================================== // // MAIN // ======================================================================== // void main(void) { printf("Starting...\n"); U00 = TRUE; waitForIP(); while(1) { printf("uptime: %d\n", SDS_get_u(3)); if (U00 == TRUE) { // příkaz restartovat program wait(500); UDPTimeStamp = 0; packetID = 0; LoraTimeStamp = 0; loraStatus = FALSE; SDS_serial_config(BUS_ID_RS485, 19200, 9, 1, 2); loadFromFlash(); U00 = FALSE; } if (U02 == TRUE) { // příkaz zvenku zahájit enumeraci enumeration(); U02 = FALSE; } if (U06 == TRUE) { // příkaz uložit adresy a typy senzorů do data flash saveToFlash(); U06 = FALSE; } if (U07 == TRUE) { // příkaz vymazat flash deleteFlash(); U07 = FALSE; } readSensors(); sendDataToWebPage(); if (U08 == FALSE) { printf("Sending to server not enabled...\n"); UDPTimeStamp = 0; } else { if (SDS_get_u(3) - UDPTimeStamp >= U12 * 6000 || UDPTimeStamp == 0) { UDPTimeStamp = SDS_get_u(3); printf("uptime: %d\n", SDS_get_u(3)); if (waitForIP() == TRUE) { // pokud mám IP od DHCP, odešlu na server sendToServer(); } else { printf("Couldn't load IP\n"); } } } if (U09 == FALSE) { printf("Encryption not enabled...\n"); } if (U10 == FALSE) { printf("LoRa not enabled...\n"); LoraTimeStamp = 0; } else { if (loraStatus == FALSE) { U11 = TRUE; LoRapwr = 0; int data = 0; SDS_serial_config(BUS_ID_LORA, 57600, 8, 1, 0); printf("Serial config 57600, 8, 1, 0\n"); factoryreset(); // connect to LoRa network senddataLora("mac join abp\r\n"); if (readdataLora() == 0) { printf("Chyba provedení příkazu mac join abp\n"); return; } if (strcmp(_answer, "ok\r\naccepted\r\n") != 0) { printf("Chyba připojení do sítě"); wait(10000); //10s prodleva na zpracovani zpravy return; } LoRapwr = getOutputPower(); loraStatus = TRUE; } if (SDS_get_u(3) - LoraTimeStamp >= U13 * 6000 || LoraTimeStamp == 0) { U11 = TRUE; LoraTimeStamp = SDS_get_u(3); printf("uptime: %d\n", SDS_get_u(3)); // setOutputPower(LoRapwr); // LoRapwr = getOutputPower(); printf("Tx power index: %d\n", LoRapwr); sendAddrLora(addrArray); wait(MESSAGE_INTERVAL); sendAddrLora(typeArray); wait(MESSAGE_INTERVAL); sendValuesLora(tempArray); wait(MESSAGE_INTERVAL); sendValuesLora(humArray); wait(MESSAGE_INTERVAL); sendValuesLora(moiArray); wait(MESSAGE_INTERVAL); sendValuesLora(resiArrayHI); wait(MESSAGE_INTERVAL); sendValuesLora(resiArrayLO); wait(MESSAGE_INTERVAL); sendValuesLora(temp2Array); wait(MESSAGE_INTERVAL); sendValuesLora(hum2Array); U11 = FALSE; } } for(int i = 0; i < sensorCount; i++) { printf("%d | ", addrArray[i]); } printf("\n"); for(int i = 0; i < sensorCount; i++) { printf("%d | ", typeArray[i]); } printf("\n"); for(int i = 0; i < sensorCount; i++) { printf("%d | ", tempArray[i]); } printf("\n"); for(int i = 0; i < sensorCount; i++) { printf("%d | ", humArray[i]); } printf("\n"); for(int i = 0; i < sensorCount; i++) { printf("%d | ", moiArray[i]); } printf("\n"); for(int i = 0; i < sensorCount; i++) { printf("%d | ", (resiArrayHI[i] << 16) | resiArrayLO[i]); } printf("\n"); for(int i = 0; i < sensorCount; i++) { printf("%d | ", temp2Array[i]); } printf("\n"); for(int i = 0; i < sensorCount; i++) { printf("%d | ", hum2Array[i]); } printf("\n"); echoclear(); } }