BWP-SS19-01/Fein Design/BLEundLogging

Aus Verteilte Systeme - Wiki
Zur Navigation springen Zur Suche springen

Mittels der Funktion void ble_set_data(char *data, int art_der_daten); kann jedes Modul eine Nachricht absenden.
Intern arbeitet die Funktion mit einem Switch-case, um je nach Inhalt die ersten 4 Bits in der Bluetooth-Nachricht entsprechend zu setzen.


Protokoll-Flags
- "F1 A0" ENERGIEMANAGEMENTSYSTEM_SUCCESS
- "F1 A1" ENERGIEMANAGEMENTSYSTEM_WARNING
- "F1 A2" ENERGIEMANAGEMENTSYSTEM_ERROR
- "F1 A3" ENERGIEMANAGEMENTSYSTEM_FATAL_ERROR
- "F1 A4" ENERGIEMANAGEMENTSYSTEM_AKKU
- "F1 A5" ENERGIEMANAGEMENTSYSTEM_SLEEP
- "F2 A0" ODOMETRY_SUCCESS
- "F2 A1" ODOMETRY_WARNING
- "F2 A2" ODOMETRY_ERROR
- "F2 A3" ODOMETRY_FATAL_ERROR
- "F3 A0" MAINCONTROL_SUCCESS
- "F3 A1" MAINCONTROL_WARNING
- "F3 A2" MAINCONTROL_ERROR
- "F3 A3" MAINCONTROL_FATAL_ERROR
- "FF FF" UNDEFINED NACHRICHT
Beispielsweise sieht ein Log-Eintrag wie folgt aus:
12 2018-12-25 09:27:53 ENERGIEMANAGEMENT SUCCESS: AKKU: 33.6

Nach dem setzen der Nachricht wird innerhalb der o.g. Funktion die Sende-Funktion void send_ble_msg(char *data); aufgerufen und mittels bt_le_adv_start(...); das Senden gestartet.
Die Funktion ist Teil des Zephyr-Systems und befindet sich unter bluetooth/bluetooth.h.

Auf der anderen Seite wird das gesendete Signal empfangen. Dies passiert mittels einem BLE-USB-Stick, einem Laptop und einem Python-Script.
Das Python-Script nutzt die 'bluepy'-Bibliothek, welches [| hier] verfügbar ist.

Das Script empfängt zum Einen die Nachricht und zum Anderen werden die übermittelten Hex-Zeichen in ASCII-Zeichen umgewandelt, damit es für den Mensch besser lesbar ist.
Hier werden die ersten 4 Bits berücksichtigt und je nach Flag die Nachricht entsprechende dekodiert.
Zusätzlich werden die geloggten Informationen mittels mehreren .txt zu einer finalen, sortierten Version zusammengefasst.
Da das Senden zwischen Server und Client nicht synchronisiert wird, kommen hier "Sende-IDs" zum Einsatz, um die korrekte Reihenfolge zwischen senden und empfangen zu erhalten.
Beim Absenden der BLE-Nachricht wird am Ende ein Trennzeichen (&) eingefügt, dahinter wird die eine fortlaufende ID angehangen. Diese ID wird erst nach einem Neustart/Reset des Feathers resettet.


# only runs with sudo
# sudo ble.py filename (without .txt)
import bluepy
from bluepy.btle import Scanner, DefaultDelegate
import sys
import datetime
import struct
import os
textFile = ""
removeFiles = 0
class ScanDelegate(DefaultDelegate):
    def __init__(self):
        DefaultDelegate.__init__(self)
        global textFile
        textFile = sys.argv[1]

    def handleDiscovery(self, dev, isNewDev, isNewData):
        if isNewDev:
            print "Discovered device", dev.addr
        elif isNewData:
            print "Received new data from", dev.addr

scanner = Scanner().withDelegate(ScanDelegate())
# how long should this scan run? (in seconds)
devices = scanner.scan(60.0)
f = open(textFile + ".txt", "w+")
for dev in devices:
    print "Device %s (%s), RSSI=%d dB" % (dev.addr, dev.addrType, dev.rssi)
    for (adtype, desc, value) in dev.getScanData():
        f.write("%s = %s\n" % (adtype, value))
f.close()

# lets copy the file to keep the full information
textFileNew = textFile + "New" + ".txt"

setHex = "0x"
# now, lets read this file
fIn = open(textFile + ".txt", "r")
fOut = open(textFile + "New" + ".txt", "a+")
# check if append-open works 
# if file was not created yet, create it
if fIn.mode == 'r' and fOut.mode == "a+":
	# read first line
	contents = fIn.readline()
	timestamp = datetime.datetime.now()
	while contents:
		# content starting with 255 is the message
		if "255" in contents:
			# slice the message (remove "255 = ")
			msg = contents[6:]
			# check first two bits and bit 3 and 4 
			if "f1" in msg[:2] and "a0" in msg[2:4]:
				timestamp = datetime.datetime.now()
				toWrite = str(timestamp)+" ENERGIEMANAGEMENT SUCCESS: "
				# write to file
				fOut.write(toWrite)
			if "f1" in msg[:2] and "a1" in msg[2:4]:
				timestamp = datetime.datetime.now()
				toWrite = str(timestamp)+" ENERGIEMANAGEMENT WARNING: "
				fOut.write(toWrite)
			if "f1" in msg[:2] and "a2" in msg[2:4]:
				timestamp = datetime.datetime.now()
				toWrite = str(timestamp)+" ENERGIEMANAGEMENT ERROR: "
				fOut.write(toWrite)
			if "f1" in msg[:2] and "a3" in msg[2:4]:
				timestamp = datetime.datetime.now()
				toWrite = str(timestamp)+" ENERGIEMANAGEMENT FATAL_ERROR: "
				fOut.write(toWrite)
			if "f1" in msg[:2] and "a4" in msg[2:4]:
				timestamp = datetime.datetime.now()
				toWrite = str(timestamp)+" ENERGIEMANAGEMENT AKKU: "
				fOut.write(toWrite)			
			if "f2" in msg[:2] and "a0" in msg[2:4]:
				timestamp = datetime.datetime.now()
				toWrite = str(timestamp)+" ODOMETRY SUCCESS: "
				fOut.write(toWrite)
			if "f2" in msg[:2] and "a1" in msg[2:4]:
				timestamp = datetime.datetime.now()
				toWrite = str(timestamp)+" ODOMETRY WARNING: "
				fOut.write(toWrite)
			if "f2" in msg[:2] and "a2" in msg[2:4]:
				timestamp = datetime.datetime.now()
				toWrite = str(timestamp)+" ODOMETRY ERROR: "
				fOut.write(toWrite)
			if "f2" in msg[:2] and "a3" in msg[2:4]:
				timestamp = datetime.datetime.now()
				toWrite = str(timestamp)+" ODOMETRY FATAL_ERROR: "
				fOut.write(toWrite)
			if "f3" in msg[:2] and "a0" in msg[2:4]:
				timestamp = datetime.datetime.now()
				toWrite = str(timestamp)+" MAINCONTROL SUCCESS: "
				fOut.write(toWrite)
			if "f3" in msg[:2] and "a1" in msg[2:4]:
				timestamp = datetime.datetime.now()
				toWrite = str(timestamp)+" MAINCONTROL WARNING: "
				fOut.write(toWrite)
			if "f3" in msg[:2] and "a2" in msg[2:4]:
				timestamp = datetime.datetime.now()
				toWrite = str(timestamp)+" MAINCONTROL ERROR: "
				fOut.write(toWrite)
			if "f3" in msg[:2] and "a3" in msg[2:4]:
				timestamp = datetime.datetime.now()
				toWrite = str(timestamp)+" MAINCONTROL FATAL_ERROR: "
				fOut.write(toWrite)
			if "ff" in msg[:2] and "ff" in msg[2:4]:
				timestamp = datetime.datetime.now()
				toWrite = str(timestamp)+" UNDEFINED NACHRICHT: "
				fOut.write(toWrite)
			# slice the message from bit 5 to the end
			newMsg = msg[4:]
			# the first appear of the "00" string shows the end of the message!
			findMsg = newMsg.find("00")
			for i in range(0, findMsg, 2):
				# slice every 2 bits
				toConvert = newMsg[i:i+2]
				zahl = int(setHex+toConvert,16)
				#print zahl,'=>',chr(zahl)
				# write ASCII text to the file
		       		fOut.write(chr(zahl))
			fOut.write("\n")
		contents = fIn.readline()
fIn.close()
fOut.close()

fIn = open(textFile + "New.txt", "r")
fOut = open(textFile + "NewSorted.txt", "a+")
if fIn.mode == 'r' and fOut.mode == "a+":
	contents = fIn.readline()
	while contents:
		# find & at the end of the message
		# the & declares the beginning of the id number
		findSplit = contents.find("&")
		# split message to get id
		toWrite = contents[findSplit+1:]+contents[:findSplit]
		replaceBN = toWrite.replace("\n"," ")
		fOut.write(replaceBN)
		fOut.write("\n")		
		contents = fIn.readline()
fIn.close()
# linux sort command
linuxCMDSort = "sudo sort -n -o " + "sorted.txt " + textFile + "NewSorted.txt"
fOut.close()
# run sort command
os.system(linuxCMDSort)
if removeFiles == 1:
	linuxCMDRM1 = textFile + ".txt"
	linuxCMDRM2 = textFile + "New.txt"
	linuxCMDRM3 = textFile + "NewSorted.txt"
	os.remove(linuxCMDRM1)
	os.remove(linuxCMDRM2)
	os.remove(linuxCMDRM3)
	print ".txt files are removed..\n"
else:
	print ".txt files are not removed..\n"