Prototyputrustningen kan användas till det önskade ändamålet enligt det utförande som föreslagits i detta examensarbete. Det kan däremot vara av intresse att göra vissa fortsatta eller kompletterande utredningar. Framför allt skulle det vara lämp-ligt att ekonomiskt och underhållsmässigt utreda möjligheterna att ansluta fler en-heter med samma funktion som enhet 1 till enhet 2. Då kan fler områden övervakas genom att enbart addera en mikrokontrollplattform. Begräsningarna uppkommer i enhet 2 där speglingen av I/O i så fall sker från fler områden. En lämplig lösning på problemet är då att använda en Arduino MEGA 2560 som mikrokontrollerplattform som har fler I/O än Arduino UNO, se kapitel 2.1.2.1. Funktionen har förberetts med förslag på hur enhet 2 kan känna igen olika enheter, ”enhets ID” kan användas i det syftet.
För att stärka skyddet mot avlyssning är en lämplig fortsättning av projektet att im-plementera antingen RSA eller AES kryptering. En starkare kryptering utesluter be-hovet att göra en enskild bedömning av hur stark krypteringen behöver vara.
Om prototyputrustningen ska användas i en stor kvantitet är det lämpligt att genom-föra kompletteringar relaterad till området tillförlitlighet. Detta examenarbete utgår ifrån data till Arduino UNO:s komponenter för beräkningarna. Genom att genom-föra tester och mätningar på enheterna som används skulle resultatet i detta arbete kunna valideras, alternativt revideras. Metoden behandlas inte i detta examensarbete utan nämns bara ytligt som ett av två alternativ i kapitel 2.6.
Referenser
[1] “Transforming our world: the 2030 Agenda for Sustainable Development .:. Sustainable Development Knowledge Platform.” [Online]. Available:
https://sustainabledevelopment.un.org/post2015/transformingourworld. [Accessed: 22-Mar-2020].
[2] “Skyddslag (2010:305) Svensk författningssamling 2010:2010:305 t.o.m. SFS 2019:941 - Riksdagen.” [Online]. Available:
https://www.riksdagen.se/sv/dokument-lagar/dokument/svensk-forfattningssamling/skyddslag-2010305_sfs-2010-305. [Accessed: 19-May-2020].
[3] “Microcontroller Invention History - Who Invented first Microcontroller.” [Online]. Available: http://www.circuitstoday.com/microcontroller-invention-history. [Accessed: 15-Mar-2020].
[4] “Microcontrollers - Overview - Tutorialspoint.” [Online]. Available:
https://www.tutorialspoint.com/microprocessor/microcontrollers_overvie w.htm. [Accessed: 15-Mar-2020].
[5] “Introduction to Microcontroller - OpenLabPro.com.” [Online]. Available: https://openlabpro.com/guide/basics-of-microcontroller/. [Accessed: 15-Mar-2020].
[6] “1. The Arduino Family - Arduino: A Technical Reference [Book].” [Online]. Available:
https://www.oreilly.com/library/view/arduino-a-technical/9781491934319/ch01.html. [Accessed: 20-Mar-2020]. [7] “Arduino Official Store | Boards Shields Kits Accessories.” [Online].
Available: https://store.arduino.cc/. [Accessed: 15-Mar-2020]. [8] “Arduino - Warranty.” [Online]. Available:
https://www.arduino.cc/en/Main/warranty. [Accessed: 19-May-2020]. [9] “Arduino - Introduction.” [Online]. Available:
https://www.arduino.cc/en/Guide/Introduction. [Accessed: 20-Mar-2020].
[10] T. Arduino et al., “Arduino Tutorial for Ethernet Shield,” 2010. [11] K. & Co, Hur funkar Arduino? Kjell & Co, 2016.
[12] “Arduino - Libraries.” [Online]. Available:
https://www.arduino.cc/en/Reference/Libraries. [Accessed: 19-May-2020].
[13] “Mikrobrytare | OEM Automatic AB.” [Online]. Available: https://www.oemautomatic.se/produkter/sensor-,-a-,-maskinsäkerhet/mikrobrytare. [Accessed: 19-May-2020].
[14] N. Arya and A. P. Singh, “Fault tolerant design of digital systems,” in IET
Conference Publications, 2016, vol. 2016, no. CP739, doi:
10.1049/cp.2016.1534.
[15] B. W. Johnson, “Fault-tolerant Microprocessor-based Systems,” IEEE Micro, vol. 4, no. 6, pp. 6–21, 1984, doi: 10.1109/MM.1984.291277.
[16] A. Avizienis, “Fault-Tolerant Systems,” IEEE Trans. Comput., vol. C–25, no. 12, pp. 1304–1312, 1976, doi: 10.1109/TC.1976.1674598.
[18] A. C. Persya, “Fault-Tolerant Real-Time Systems,” Fault-Tolerant Real-Time
Syst., pp. 177–180, 1996, doi: 10.1007/b102609.
[19] R. Manuel and F. Lapa, “Intruder Alarm Systems - The Road Ahead,” in
Advanced Technologies, InTech, 2009.
[20] N. O. Loop, N. C. Loop, and S. B. Loop, “Wired loop principles | Jablotron Wired loop principles Wired loop principles | Jablotron,” pp. 1–2, 2009. [21] “kryptologi - Uppslagsverk - NE.se.” [Online]. Available:
https://www.ne.se/uppslagsverk/encyklopedi/lång/kryptologi. [Accessed: 19-May-2020].
[22] E. Sahinaslan and O. Sahinaslan, “Cryptographic methods and development stages used throughout history,” AIP Conf. Proc., vol. 2086, no. April, 2019, doi: 10.1063/1.5095118.
[23] S. Singh, The Code Book: How to make it, break it, hack it, crack it. 2001. [24] “Beskrivning av symmetrisk och asymmetrisk kryptering.” [Online].
Available: https://support.microsoft.com/sv-se/help/246071. [Accessed: 19-May-2020].
[25] S. Nisha and M. Farik, “RSA Public Key Cryptography Algorithm A Review,”
Int. J. Sci. Technol. Res., vol. 06, no. 07, pp. 187–191, 2017.
[26] B. Rothke, “A look at the Advanced Encryption Standard (AES),” Inf. Secur.
Manag. Handbook, Sixth Ed., pp. 1151–1158, 2007, doi:
10.1201/9781439833032.ch89.
[27] “What is AES? | TechRadar.” [Online]. Available:
https://www.techradar.com/news/what-is-aes. [Accessed: 21-May-2020]. [28] J. G. Elerath and M. Pecht, “IEEE 1413: An IEEE standard for reliability
predictions,” Proc. - 2010 11th Int. Conf. Electron. Packag. Technol. High Density
Packag. ICEPT-HDP 2010, no. January 2010, pp. 1–6, 2010, doi:
10.1109/ICEPT.2010.5582388.
[29] F. O. Ehiagwina, T. O. Adewunmi, E. O. Seluwa, O. O. Kehinde, and N. S. Abubakar, “A Comparative Overview of Electronic Devices Reliability Prediction Methods-Applications and Trends,” Majlesi J. Telecommun. Devices, no. December, 2017.
[30] DoD, “Reliability Prediction of Electronic Equipment (Military Handbook),”
Dep. Def. USA, p. 205, 1991.
[31] S. Pokorni, “Reliability Prediction of Electronic Equipment : Problems and Experience RELIABILITY PREDICTION OF ELECTRONIC
EQUIPMENT : PROBLEMS AND EXPERIENCE,” no. October 2016, 2019.
[32] S. Pokorni, “PROBLEMS OF RELIABILITY PREDICTION OF ELECTRONIC EQUIPMENT,” no. September 2014, 2019.
[33] G. Gupta, R. P. Mishra, and P. Jain, “Reliability analysis and identification of critical components using Markov model,” in IEEE International Conference on
Industrial Engineering and Engineering Management, 2016, vol. 2016-January,
pp. 777–781, doi: 10.1109/IEEM.2015.7385753.
[34] S. S. Jolly and B. J. Singh, “An approach to enhance availability of repairable systems: A case study of spms,” Int. J. Qual. Reliab. Manag., vol. 31, no. 9, pp. 1031–1051, Sep. 2014, doi: 10.1108/IJQRM-02-2014-0016.
[35] D. A. Rennels, “Fault-Tolerant Computing—Concepts and Examples,” IEEE
Trans. Comput., vol. C–33, no. 12, pp. 1116–1129, 1984, doi:
10.1109/TC.1984.1676390.
[36] M. Catelani, L. Ciani, and M. Venzi, “RBD Model-Based Approach for Reliability Assessment in Complex Systems,” IEEE Syst. J., vol. 13, no. 3, pp. 2089–2097, Sep. 2019, doi: 10.1109/JSYST.2018.2840220.
Bilaga A
I denna bilaga presenteras ett par fördjupningstips inom ramen för de teorier och metoder som presenteras i kapitel 2. Artiklarna lämnas åt läsaren att avgöra innehål-lets relevans.
1: Introductory Microcontroller Programming – Peter Alley 2011
2: Overview of Architectures with Arduino Boards as Building Blocks for Data Ac-quisition and Control Systems – V.M. Cvjetkovic, M. Matijevic - 2016
3: Advanced Encryption Standard – Douglas Selent 2010 4: Moderna krypteringssystem – Eva-Maria Vikström 2006
5: A new Symmetric Key Encryption Algorithm With Higher Performance, Abid Murtaza, Syed Jahanzeb Hussain Pirzada, Liu Jianwei 2019
6: Fault Tolerance for Real-Time Systems: Analysis and Optimization of Roll-back Recovery with Checkpointing – Nikolov Dimitar 2014
7: Reliability Analysis of Electrical Power System Using Graph Theory and Reliability Block Diagram - Bouziane Boussahoua, Ali Elmaouhab 2019 8: Markov Approach to Finding Failure Times of Repairable Systems – John A. Buzacott 1970
9: The Design and Analysis of Fault Tolerant Digital Systems – B.W. Johnsson 1989 10: Better prediction of software failure times using order statistics – Nasser Ab-osaq, Walter Bond – 2009
Bilaga B
Fig. B1 visar hur en potentiometer ansluts till en Arduino UNO via en analog in-gång. Fig. B2 visar hur en LED anslut till en Arduino UNO via en digital utin-gång. Ex-emplen är hämtade från Arduino.
Bilaga C
I Fig. C1 visas ett exempel på en ”Vigenére fyrkant”. Fyrkanten är uppbyggd av det svenska alfabetet där endast gemener har använts.
Bilaga D
I den här bilagan presenteras den uträknings som ligger till grund för de resulterande resistorvärdena för den dubbelbalanserade slingan som presenteras i kapitel 3.2.3.1. Beräkningarna baseras på principen av spänningsdelning enligt kretsen i Fig. D1 och ekvation (D1). De tre tillstånd som krävs för beräkningarna kan ses i Fig. D2 – D4. Genomgående används samma benämningar i ekvationerna som i figurerna i denna bilaga. Beräkningarna är baserad på en förväntad uppmätt spänning enligt:
𝑇𝑖𝑙𝑙𝑠𝑡å𝑛𝑑 1: 4𝑉 𝑇𝑖𝑙𝑙𝑠𝑡å𝑛𝑑 2: 1,5𝑉 𝑇𝑖𝑙𝑙𝑠𝑡å𝑛𝑑 3: 5𝑉 𝑉𝑢𝑡= 𝑍2 𝑍1 + 𝑍2𝑉𝑖𝑛 (D1) I detta examensarbete är: 𝑉𝑢𝑡 = 𝐴 − 𝐼𝑁 𝑉𝑖𝑛 = 5𝑉 Vilket resulterar i: 𝐴 − 𝐼𝑁 = 𝑍2 𝑍1 + 𝑍25𝑉 Tillstånd 1:
Identifierar 𝑍1, 𝑍2 och 𝐴 − 𝐼𝑁samt stoppar in dem i ekvation (D1) och bildar ekvat-ion (D2): { 𝐴 − 𝐼𝑁 = 4𝑉 𝑍1 = 𝑅1Ω 𝑍2 = 𝑅3Ω 4𝑉 = 𝑅3Ω 𝑅1Ω + 𝑅3Ω5𝑉 (D2)
Ekvation (D2) ger ekvation (D3):
𝑅1 =1
Tillstånd 2:
Identifierar 𝑍1, 𝑍2 och 𝐴 − 𝐼𝑁 samt stoppar in dem i ekvation (D1) och bildar ekvat-ion (D4): { 𝐴 − 𝐼𝑁 = 1,5𝑉 𝑍1 = 𝑅1Ω + 𝑅2Ω 𝑍2 = 𝑅3Ω 1,5𝑉 = 𝑅3Ω 𝑅1Ω + 𝑅2Ω + 𝑅3Ω5𝑉 (D4)
Ekvation (D4) ger ekvation (D5):
𝑅2 =7
3𝑅3 − 𝑅1 (D4)
Genom att stoppa in ekvation (D3) i ekvation (D5) erhålls ekvation (D6):
𝑅2 =7 3𝑅3 − 1 4𝑅3 = 25 12𝑅3 (D6) Tillstånd 3:
Identifierar 𝑍1, 𝑍2 och 𝐴 − 𝐼𝑁 samt stoppar in dem i ekvation (D1) och bildar ekvat-ion (D7): { 𝐴 − 𝐼𝑁 = 5𝑉 𝑍1 = 0Ω 𝑍2 = 𝑅3Ω 5𝑉 = 𝑅3Ω 0Ω + 𝑅3Ω5𝑉 (D7)
Ekvation (D7) ger ekvation (D8):
𝑅3 = 𝑅3 (D8)
Enligt ekvation (D3), (D6) och (D8) erhålls värdena på 𝑅1, 𝑅2 och 𝑅3.
{ 𝑅1 =1 4𝑅3 𝑅2 =25 12𝑅3 𝑅3 = 𝑅3
Resulterande värden:
𝑅1 och 𝑅2 beror av storleken på 𝑅3 som i sin tur är oberoende. 𝑅3 = 4700Ω antas fortsättningsvis. Resistorvärdet 𝑅3 är baserat på tillgången av resistorer hos författa-ren.
𝑅1 och 𝑅2 beräknas enligt:
{ 𝑅1 =1 44700Ω = 1175Ω ≈ 1200Ω 𝑅2 =25 124700Ω = 9790Ω ≈ 10000Ω R3 = 4700Ω
Vilket leder till slutresultat:
{
𝑅1 = 1200Ω 𝑅2 = 10000Ω
𝑅3 = 4700Ω
Kontroll:
Genom att beräkna ekvation (D1) med värdena på 𝑅1, 𝑅2 och 𝑅3 kontrolleras spän-ningsnivåerna för tillstånd 1 och 2:
𝑇𝑖𝑙𝑙𝑠𝑡å𝑛𝑑 1: 𝐴 − 𝐼𝑁 = 4700Ω
1200Ω + 4700Ω5𝑉 = 3.98𝑉 ≈ 4V 𝑇𝑖𝑙𝑙𝑠𝑡å𝑛𝑑 2: 𝐴 − 𝐼𝑁 = 4700Ω
Figur D1 – Principkrets för spänningsdelning. Vut är matande spänning. Z1 och Z2 är motstånd. Vin läser av spänningen över Z2.
Figur D2 – Kretsen som motsvarar tillstånd 1: Stäng mikrobrytare.
Figur D3 - Kretsen som motsvarar tillstånd 2: Öppen mikrobrytare.
Bilaga E
I den här bilagan presenteras den kod som skrivits till enhet 1 och enhet 2.
ENHET 1:
// Program created by: Stefan Wernhager // Date: 2020-05-28
// Description: UNIT 1:
// This
pro-gram reads analog input. Depending on the reading it ether sends it to unit 2 or waits until unit 2 asks for it, then sends it. // Before it sends data its encrypted. // See report for more details
//////////////////////////////////////// CONFIGURATION //////////////////////////////////////// ////////// Include libraries #include <SPI.h> #include <Ethernet.h> #include <avr/wdt.h>
////////// Ethernet communication configuration byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; IPAddress ip(192, 168, 1, 176); IPAddress gateway(192, 168, 1, 1); IPAddress subnet(255, 255, 255, 0); int port = 23; EthernetClient client; EthernetServer server(port); IPAddress unit2(192, 168, 1, 177); ////////// Device configuration
String unitID = "UNO001"; // The ID of this particular unit
const int sendIntervalMS = 1000; // The inter-val to send data if unnormal state is reached
const int analogPins[] = {A0, A1, A2, A3, A4, A5}; // A0 - A2 = Area 1, A3 - A5 = Area 51
////////// Device communication configuration
String sepMsg = "%"; // Sign that separates parts in the text mes-sage sent between devises
String endMsg = "!"; // Sign that tells that this is the end of the message
String unit2Command; boolean wait;
String waitUnit2 = "W"; String alarmUnit2 = "+"; char command[2] = {'C', 'A'}; char commandChar; String commandRandomNbr; String commandKeyPosition1; String commandKeyPosition2; String clearMsg; char tempChar;
////////// Crypt configuration int firstKey[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227}; // 10-58 st int secondKey[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227}; // 10-58 st int keyPos[2]; int key[2]; String encryptedMsg; ////////// Program variables int i;
unsigned long previousMillis = 0; unsigned long currentMillis; int state[2];
boolean alarm[2] = {false, false}; float voltage[2];
int voter[2];
//////////////////////////////////////// INITIALIZATION ////////////////////////////////////////
void setup() {
Ethernet.begin(mac, ip, gateway, subnet); // Init ethernet delay(1000); // Ethernet init time Serial.begin(9600); // Init serial port communication
while (!Serial) ; // Wait until its con-nected.
// Init analog pins
for (i = 0; i < sizeof(analogPins); i++) pinMode(analogPins[i], INPUT);
Serial.println("***** THIS IS UNIT 1 Program version 1.0 *****"); } //////////////////////////////////////// MAIN PROGRAM //////////////////////////////////////// void loop() { // Enable watchdog wdt_enable(WDTO_8S);
// Read sensorvalues from area 1 and area 2
// Check the input values for area1/2 with the voting algorithm, set alarmArea1/2 true if ADC differs from each other (Unnormal) voter[0] = majorityVoter(analogRead(analogPins[0]),
analogRead(analogPins[1]), analogRead(analogPins[2]), 1); // Read A0 - A2 = Area 1
voter[1] = majorityVoter(analogRead(analogPins[3]),
analogRead(analogPins[4]), analogRead(analogPins[5]), 2); // Read A3 - A5 = Area 2
// Check the state of the ADC values for area 1/2, set
alarmArea1/2 true if value are in the wrong state (Unnormal state) if (voter[0] != 9999) state[0] = checkState(voter[0]);
else state[0] = 3;
if (state[0] != 1) alarm[0] = true;
if (voter[1] != 9999) state[1] = checkState(voter[1]); else state[1] = 3;
// If alarm[0] or alarm[1] are HIGH, then we got un-normal
state, send data continuously during a predefined interval to unit 2
if ( alarm[0] || alarm[1]) { currentMillis = millis();
if ( (currentMillis - previousMillis) >= sendIntervalMS) { previousMillis = currentMillis;
// Put together the data to send
clearMsg = unitID + sepMsg + String(voter[0]) + sepMsg + String(alarm[0]) + sepMsg + String(state[0]) + sepMsg +
String(voter[1]) + sepMsg + String(alarm[1]) + sepMsg + String(state[1]); // Generate keys keyPos[0] = random(10, 58); keyPos[1] = random(10, 58); key[0] = firstKey[keyPos[0]]; key[1] = secondKey[keyPos[1]];
// Create string with the encrypted data and add the key po-sitions in front, send data to unit 2
encryptedMsg = alarmUnit2 + String(keyPos[0]) + String(key-Pos[1]) + String(encryptString(clearMsg, key[0], key[1])) + endMsg;
alarmSendToUnit2(encryptedMsg, unit2, port); encryptedMsg = ""; clearMsg = "";
} }
// If state is unchanged, run as normal and If something is re-ceived from master process it
unit2Command = communicateWithUnit2(waitUnit2); if ( unit2Command.length() > 0 ) {
// Divide message into useful parts
for (i = 0; i < unit2Command.length(); i++) { char temp = unit2Command[i];
if (i == 0) commandChar = temp; // Save the command identi-fier (First sign)
if (i > 0 && i < 6) commandRandomNbr += temp; // Save the 5 digit random number
if (i == 6 || i == 7 ) commandKeyPosition1 += temp; // Save the position for the first key
if (i > 7 && i < unit2Command.length()) commandKeyPosition2 += temp; // Save the position for the second key
}
// Get the keys
key[0] = firstKey[commandKeyPosition1.toInt()]; key[1] = secondKey[commandKeyPosition2.toInt()]; // Depending on the command C or A from unit 2
// C: Send unitID, ADC Area 1, alarm Area 1, state Area 1, ADC Area 2, alarm Area 2, state Area 2
// A: Send unitID, the random number received from unit 2, alarm Area 1, state Area 1, the random number received from unit 2, alarm Area 2, state Area 2
if (commandChar == command[0]) // C
clearMsg = unitID + sepMsg + String(voter[0]) + sepMsg + String(alarm[0]) + sepMsg + String(state[0]) + sepMsg +
String(voter[1]) + sepMsg + String(alarm[1]) + sepMsg + String(state[1]);
else if (commandChar == command[1]) // A
clearMsg = unitID + sepMsg + commandRandomNbr + sepMsg + String(alarm[0]) + sepMsg + String(state[0]) + sepMsg + com-mandRandomNbr + sepMsg + String(alarm[1]) + sepMsg +
else clearMsg = "";
// Encrypt the answer, add the termination sign and send it to Unit 2
encryptedMsg = String(encryptString(clearMsg, key[0], key[1])) + endMsg;
communicateWithUnit2(encryptedMsg); // Delete datastrings
tempChar = ' '; commandRandomNbr = ""; commandKeyPosition1 = ""; commandKeyPosition2 = ""; clearMsg = ""; encryptedMsg = ""; } // Reset Watchdog wdt_reset(); } //////////////////////////////////////// FUNCTIONS ////////////////////////////////////////
int majorityVoter( int ADC1, int ADC2, int ADC3, int Area) { // Majority voter algorithm with the possibility to set are-aAlarm HIGH/LOW
int temp = 9999;
int ADCArr[3] = {ADC1, ADC2, ADC3}; int tempArr[2] = {0, 2};
int hyst = 15;
if ( (abs(ADC1 - ADC2) < hyst) && (abs(ADC1 - ADC3) < hyst) && (abs(ADC2 - ADC3) < hyst) ) {
temp = random(0, 2); // 111 if (Area == 1) alarm[0] = false; if (Area == 2) alarm[1] = false; }
if ( (abs(ADC1 - ADC2) < hyst) && (abs(ADC1 - ADC3) > hyst) && (abs(ADC2 - ADC3) > hyst) ) {
temp = random(0, 1); // 110 if (Area == 1) alarm[0] = true; if (Area == 2) alarm[1] = true; }
if ( (abs(ADC1 - ADC2) > hyst) && (abs(ADC1 - ADC3) > hyst) && (abs(ADC2 - ADC3) < hyst) ) {
temp = random(1, 2); // 011 if (Area == 1) alarm[0] = true; if (Area == 2) alarm[1] = true; }
if ( (abs(ADC1 - ADC2) > hyst) && (abs(ADC1 - ADC3) < hyst) && (abs(ADC2 - ADC3) > hyst) ) {
temp = tempArr[random(0, 1)]; // 101 if (Area == 1) alarm[0] = true; if (Area == 2) alarm[1] = true; }
if ( (abs(ADC1 - ADC2) > hyst) && (abs(ADC1 - ADC3) > hyst) && (abs(ADC2 - ADC3) > hyst) ) {
temp = random(0, 2); // 000 if (Area == 1) alarm[0] = true; if (Area == 2) alarm[1] = true; return 9999;
}
return ADCArr[temp] ; }
int checkState(int ADCvalue) { // 0 V = kable cut - Sumalarm
// 4 V = Normal state switch closed - I/O signal // 1,5 V = Switch opened - I/O signal
// 5 V = Shortned - Sumalarm int state;
float volt;
volt = float(ADCvalue * 5) / 1023;
if ( ( volt > 3.9 ) && ( volt < 4.1 ) ) state = 1; // Normal else if ( ( volt > 1.4 ) && ( volt < 1.6 ) ) state = 2; // Open else state = 3; // Alarm
return state; }
void alarmSendToUnit2(String msg, IPAddress targetIP, int port) { // This function is based on the Telnet-server example at
www.arduino.cc
// Sends data to unit 2 if the unit is in alarm state char tempChar;
if ( client.connect(targetIP, port) ) { for (i = 0; i < msg.length(); i++) { client.print(char(msg[i])); delay(1); } while (client.available()) { tempChar = char(client.read()); delay(1); if ( tempChar == '!' ) client.stop(); } } } String communicateWithUnit2(String msg) {
// This function is based on the Telnet-server example at www.arduino.cc
// Function divided into two parts.
// PART 1: Receives a command from unit 2. Responds to that with "toSend" and put a wait-flag HIGH. Then return the received com-mand to the main program.
// PART 2 sends the answer "toSend" to the command received in PART 1. If the respond is "!" then the message are delivered and it put the wait-flag LOW.
String data = "";
EthernetClient client = server.available(); delay(20); // delay 20 ms
///////////////////// PART 1 ///////////////////// while (client && !wait) {
if ( client.available() > 0) { char tempChar = client.read(); data += tempChar; if (tempChar == '!') { wait = true; server.write("W"); tempChar = ' '; client.flush(); return data; } } } ///////////////////// PART 2 ///////////////////// while (client && wait) {
for (i = 0; i < msg.length(); i++) { client.print(char(msg[i]));
Serial.println(char(msg[i])); delay(1);
}
if ( client.available() > 0) { char tempChar = client.read(); data += tempChar;
if (tempChar == '!') { wait = false; client.stop(); tempChar = ' '; client.flush(); return data; } } } }
String encryptString(String clearMsg, int key, int changeStart) { int TOTAL_LETTERS = 93; int startASCIILetters = 34; int lastASCIILetters = 127; String temp; int k; for (k = 0; k < clearMsg.length() ; k++) {
int newCharacter = int(char(clearMsg[k])) + key + (changeStart * k);
while (newCharacter > lastASCIILetters) {
if (newCharacter >= lastASCIILetters ) newCharacter = new-Character - TOTAL_LETTERS;
else if (newCharacter < startASCIILetters) newCharacter = TOTAL_LETTERS - newCharacter; } temp += char(newCharacter); } return temp; }
ENHET 2:
// Program created by: Stefan Wernhager // Date: 2020-05-28
// Description: UNIT 2: //
This program checks if unit 1 has sent data or demand data from unit 1.
// It processes the data and communicate it through digital outputs
// Se report for more details //////////////////////////////////////// KONFIGURATION //////////////////////////////////////// ////////// Include libraries #include <SPI.h> #include <Ethernet.h> #include <avr/wdt.h>
////////// Ethernet communication configuration byte mac[] = { 0xDA, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; IPAddress ip(192, 168, 1, 177); IPAddress gateway(192, 168, 1, 1); IPAddress subnet(255, 255, 255, 0); int port = 23; EthernetServer server(port); EthernetClient client; IPAddress unit1(192, 168, 1, 176); ////////// Device configuration
const int sendIntervalMS = 3000; // 3 sec interval of demanding data from unit 1
const int digitalOut[] = {2, 3, 4}; // Alarmpin = 2, Unit 1 Area 1 = 3, Unit 1 Area 2 = 4
const int resetPin = 5; // If a reset in-pin is wanted ////////// Device communication configuration
char sepMsg = '%'; // Sign that separates parts in the text mes-sage sent between devises
char endMsg = '!'; // Sign that tells that this is the end of the message
String received Data; char command;
char commands[3] = {'C', 'A', 'E'}; int commandCount = 0;
String clearMsg;
////////// UNIT 1 Specific data String unit1ID = "UNO001";
String unitID; int value[6];
boolean unit1Area[2] = {true, true}; int unit1State[2]; boolean sumAlarmUnit1; ////////// Encryption int firstKey[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227};
int secondKey[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227}; // 10-58 st int keyPos[2]; int key[2]; String stringKeyPos1; String stringKeyPos2; String crypted; String decrypted; ////////// Program variables int i; int n;
boolean alarmState = false;
unsigned long previousMillis = 0; unsigned long currentMillis; int randomNbr;
int countTransmissionCycles = 0;
int maxTransmissionCycles = 5; // Max transmission tries before alarm
boolean lostContactAlarm = false;
//////////////////////////////////////// INITIALIZATION ////////////////////////////////////////
void setup() { // Init ethernet
Ethernet.begin(mac, ip, gateway, subnet); delay(1000); // Ethernet init time
server.begin();
// Init serial port communication Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. }
// Init digital I/O
for (i = 0; i < sizeof(digitalOut); i++) { pinMode(digitalOut[i], OUTPUT);
}
pinMode(resetPin, INPUT); // Optional
Serial.println("***** THIS IS UNIT 2 Program version 1.0 *****"); } //////////////////////////////////////// MAIN PROGRAM //////////////////////////////////////// void loop() { // Enable watchdog wdt_enable(WDTO_8S); // Resetfunction if (sumAlarmUnit1) resetFunction(resetPin); // If unit 1 has sent data ()
received Data = recieveFromUnit1(); if ( receivedData.length() > 0 ) { alarmState = true;
command = commands[2]; }
// Demand data from unit 1 continuously during a predefined in-terval if the first sign is not "+".
if (char(receivedData[0]) != '+') {
if (sumAlarmUnit1) sumAlarmUnit1 = false; // Restore sumalarm unit 1
currentMillis = millis();
if ( (currentMillis - previousMillis) >= sendIntervalMS) { previousMillis = currentMillis;
commandCount++;
// Choose command C or A. Reset commandCount every 4 cycle if (commandCount == 1) command = commands[0];
else command = commands[1]; if (commandCount == 4) { commandCount = 0; }
//Generate keypositions for encryption and 5 digit random number between 10k-30k
keyPos[0] = random(10, 58); keyPos[1] = random(10, 58);
randomNbr = random(10000, 30000); // Send command to unit 1
delay(10);
clearMsg = String(randomNbr) + String(keyPos[0]) + String(keyPos[1]);
receivedData = communicateWithUnit1(command, clearMsg, endMsg, unit1, port);
// Count the number of transmissions, if it reaches a prede-fined number set alarm
countTransmissionCycles++;
if (countTransmissionCycles == maxTransmissionCycles) lostContactAlarm = true;
} }
// Decrypt the received message from unit 1 if ( receivedData.length() > 0 ) {
for (i = 1; i < receivedData.length(); i++) { char temp = recevedDiata[i];
if ( temp != '!' ) {
if ( alarmState && i < 5 ) { // Used if unit 1 has sent data
if (i == 1 || i == 2 ) stringKeyPos1 += temp; // Save the position for the first key
if (i == 3 || i == 4 ) stringKeyPos2 += temp; // Save the position for the second key
}
else crypted += temp; } if ( temp == '!' ) { if ( alarmState ) { keyPos[0] = stringKeyPos1.toInt(); keyPos[1] = stringKeyPos2.toInt(); } key[0] = firstKey[keyPos[0]]; key[1] = secondKey[keyPos[1]];
decrypted = decryptString(crypted, key[0], key[1]) + temp; }
} }
// Separate the message from unit 1 if ( decrypted.length() > 0 ) { String temp = "";
int count = 0;
// Reset countTransmissionCycles and set lostContact to false countTransmissionCycles = 0;
lostContactAlarm = false;
if ( decrypted[i] != '%' ) temp += decrypted[i]; if ( decrypted[i] == '%' || decrypted[i] == '!') { if (count == 0) unitID = temp; // Unit-ID
if (count == 1) value[0] = temp.toInt(); // ADC if case C, RandNR if case A - Area 1
if (count == 2) value[1] = temp.toInt(); // Alarm - Area 1 if (count == 3) value[2] = temp.toInt(); // State - Area 1 if (count == 4) value[3] = temp.toInt(); // ADC if case C, RandNR if case A - Area 2
if (count == 5) value[4] = temp.toInt(); // Alarm - Area 2 if (count == 6) value[5] = temp.toInt(); // State - Area 2 temp = "";
count ++; }
}
// Check Unit 1 Area 1 and Area 2
unit1Area[0] = checkUnitData(command, value[0], randomNbr); unit1Area[1] = checkUnitData(command, value[3], randomNbr); if (command == commands[0] || command == commands[2] ) { alarmState = false;
unit1State[0] = checkState(value[0]); unit1State[1] = checkState(value[3]); }
// Delete datastrings
stringKeyPos1 = ""; stringKeyPos2 = ""; clearMsg = ""; re-ceivedData = ""; crypted = ""; decrypted = "";
}
// Check sumalarm criteria, set HIGH if anything is true and re-set commandCount
if ( unitID != unit1ID || !unit1Area[0] || value[1] != 0 || !unit1Area[1] || value[4] != 0 || value[2] != unit1State[0] || value[5] != unit1State[1] || lostContactAlarm) { // Lägg ev till jämförelser mellan state i båda för extra koll
sumAlarmUnit1 = true; commandCount = 0; }
// Alarm: PIN 2
if (!sumAlarmUnit1) digitalWrite(digitalOut[0] , HIGH); // Pin 2 else digitalWrite(digitalOut[0], LOW);
// Set I/O for Unit 1 Area 1 and Area 2 HIGH or LOW depending on data
// Area 1: PIN 3 and Area 2: PIN 4
if (unit1State[0] == 1 && !lostContactAlarm) digitalWrite(dig-italOut[1], HIGH); // Pin3
else if (unit1State[0] != 1 || lostContactAlarm) digital-Write(digitalOut[1], LOW);
if (unit1State[1] == 1 && !lostContactAlarm) digitalWrite(dig-italOut[2], HIGH); // Pin4
else if (unit1State[1] != 1 || lostContactAlarm) digital-Write(digitalOut[2], LOW);
// Reset Watchdog timer wdt_reset();
//////////////////////////////////////// FUNCTIONS ////////////////////////////////////////
void resetFunction(int resetPin) { // Optional
// if (digitalRead(resetPin) == HIGH) alarm = false; // Restore alarm
}
String recieveFromUnit1() { String data = "";
EthernetClient client = server.available(); while (client) {
if ( client.available() > 0) { char tempChar = client.read(); data += tempChar; if (tempChar == '!') { server.write("!"); client.stop(); tempChar = ' '; } } } return data; }
String communicateWithUnit1(char command, String key, char termi-nate, IPAddress targetIP, int port) {
// This function is based on the Telnet-server example at www.arduino.cc
String dataToSend = String(command) + key + String(terminate); String targetAnswer = ""; char tempChar; if ( client.connect(targetIP, port) ) { while (client) { delay(1); if (tempChar != 'W') {
for (i = 0; i < dataToSend.length(); i++) { client.print(char(dataToSend[i])); delay(1); } } while (client.available()) { tempChar = char(client.read()); targetAnswer += tempChar; delay(1); if ( tempChar == 'W' ) { } if ( tempChar == '!' ) { server.write("!"); client.flush(); client.stop(); } delay(1); } } } return targetAnswer; }
String decryptString(String encryptedMsg, int key1, int key2) { int TOTAL_LETTERS = 93; int startASCIILetters = 34; int lastASCIILetters = 127; String temp; int k; for (k = 0; k < encryptedMsg.length() ; k++) {
int newCharacter = int(char(encryptedMsg[k])) - key1 - (key2 * k);
while (newCharacter < startASCIILetters) {
if (newCharacter >= lastASCIILetters ) newCharacter = new-Character - TOTAL_LETTERS;
else if (newCharacter < startASCIILetters) newCharacter = newCharacter + TOTAL_LETTERS; } temp += char(newCharacter); } return temp; }
boolean checkUnitData(char command, int value1, int value2) { boolean ok;
switch (command) { case 'A':
if (value1 != value2) ok = false; else ok = true;
break; case 'C':
if (value1 < 0 || value1 > 1024) ok = false; else ok = true;
break; case 'E':
if (value1 != value2) ok = false; else ok = true; break; default: ok = false; break; } return ok; }
int checkState(int ADCvalue) { // 0 V = cable cut – Sum-alarm
// 4 V = Normal state switch closed - I/O signal // 1,5 V = Switch open - I/O signal
// 5 V = Shortened – Sum-alarm float voltage;
int state;
voltage = float(ADCvalue * 5) / 1023;
if ( ( voltage > 3.9 ) && ( voltage < 4.1 ) ) state = 1; // Nor-mal
else if ( ( voltage > 1.4 ) && ( voltage < 1.6 ) ) state = 2; // Open
else state = 3; // Alarm return state;
Bilaga F
I denna bilaga i Fig. F1 – F8 återfinns de flödesscheman ur kapitel 3.3 och 3.4 som beskriver program och krypteringsprocess.
Figur F1 - Flödesschema över principen för hur programmet är uppbyggd med normalt- och onormalt tillstånd. Efter avläsning av I/O för område 1 och område 2 sker en kontroll av villkoren för normalt tillstånd. Uppfylls alla villkor agerar programmet efter normalt tillstånd annars agerar programmet efter onormalt tillstånd.
Figur F3 - Flödesschema över majoritetsvoteringsalgoritmen. Specialfallet där alla tre ingångar visar olika är utelämnad.
Figur F5 - Flödesschema som beskriver hur övervakningen av enhet 1 fungerar där fem misslyckade transaktionsförsök tillåts.
Figur F6 - Flödesschema som beskriver principen för enheternas kommunikation under då normaltillstånd råder.
Figur F7 - Flödesschema som beskriver principen för hur enheterna kommunicerar med varandra under normalt- och onormalt tillstånd.
Figur F8 - Flödesschema som beskriver krypteringen av en klartext K. Klartexten krypteras tecken för tecken i två steg. Resultatet blir den krypterade texten E.
Bilaga G
I Fig. G1 finns den ASCII-tabell som Arduino använder där tecken 34–126 även age-rar alfabet till den teckensubstitution som krypteringsalgoritmen använder.
Figur G1 - ASCI-tabell som används av Arduino UNO och där tecken 34–126 används som alfabet i