Datenaustausch zweischen zwei laufenden Prozessen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Dymo
User
Beiträge: 14
Registriert: Donnerstag 30. August 2018, 04:50

@__deets__:
Kann ich Dir das in Pythonista laufende App.py und das gezippte Datenfile "Amtech.rar (Zusammen ca. 21KByte) per Email zuschicken?
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Nein. Das bringt ueberhaupt nichts. Denn ohne Bluetooth geht dein Code doch nicht. Kannst du nicht einfach in 2 Minuten meinen Code in Pythonista kopieren, und mir rueckmelden, ob der tut?
Dymo
User
Beiträge: 14
Registriert: Donnerstag 30. August 2018, 04:50

Ich meinte das von mir erweiterte animate(i) von dem sentdex-Tutorial-Beispiel. In dieser Version werden die Logdaten von einem Text-File gelesen. Ich wollte damit beweisen, dass alles mit Pythonista läuft.

Ob der Sentdex berechtigt ist, seine Funktion als animate zu bezeichnen, weiß ich nicht. Für mich war wichtig, dass sich der Plot an die ankommenden Daten live anpasst. und das geht, wenndie Daten anstelle von einem fertig geschriebenen File live seriell von einem USB/COM-Port kommen.
Da die IOS-Geräte keine USB haben und ich das eigentlich drahtlos haben wollte, war Bluethooth eine Option.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ok, ich gebe auf. Es macht einen entscheidenden Unterschied fuer die Loesung des Problems zu etablieren, ob die Animate Funktionalitaet nun geht, oder eben nicht. Das hat nichts mit rechthaben zu tun, sondern mit verstehen. Denn das beeinflusst nunmal die Struktur des Programms. Da wir da aber nicht weiter kommen, weil du nicht bereit bist, dieses Wissen gemeinsam hier mit mir zu erarbeiten, hat's keinen Wert.

Pythonista hat ja ein eigenes Forum, vielleicht wird dir da geholfen. Natuerlich kann theoretisch auch hier noch jemand was dazu sagen, da du meines Wissens nach aber die erste Pythonista-Frage hier ueberhaupt gestellt hast, sind die Chancen dafuer klein.
Dymo
User
Beiträge: 14
Registriert: Donnerstag 30. August 2018, 04:50

Ich glaube nicht, dass ich dich richtig verstanden habe.

Was muss ich Konkret machen und wie kann ich bei der Realisierung deines Gedankenganges helfen?

Wenn Du meinst, dass es keinen Sinn hat, dann okay, lassen wir das. Es ging mir nie um rechthaben. Ich habe wie oft wiederholt das Problem nicht in animate-Modul gesehen, sondern im Bluetooth-Teil, dass es beim Aufruf nichts als Return, in diesem Fall eine Datenzeile, herausgibt. Alles bleibt in dem Class-Körper.

In dem Fall magst Du recht haben, dass bei der jetzigen "animate(i)"- Strucktur der Aufruf des Bluetoothmoduls nichts bringt und das animate(i)-Modul nicht an die Bluetooth-Daten heran kommt.

Andere Möglichkeit wäre, die "animate"- Funktion in die Bluetooth-Class zu integrieren. da habe ich aber keine Idee, wie die Bluetoothdaten an die Stelle des urprünglichen Daten-Input kommen sollen, ohne animate bei jeden neuen Daten von Bluetooth zu starten, Ich denke diese Struktur hatte ich mal ausprobiert und hat nicht funktioniert, sondern immer neue Plots ohne Inhalt produziert, die in der Konsole hochliefen.

Verstehen wir uns nun richtig, oder reden wir immer noch aneinander vorbei?
Dymo
User
Beiträge: 14
Registriert: Donnerstag 30. August 2018, 04:50

Hallo nochmal,

ich habe die letzten zwei Tage versucht, die __deets__-Anregungen zu verdauen und meine Teilprogramme so umzustrukturieren, dass sie in seinen Vorschlagsrahmen passen und gemeinsam laufen können.

Ich bin nun zu der Lösung gekommen, dass ich die Teile der Datenvorbereitung (Interpretation des 'line'-Inhaltes und die Aneinanderreihung der einzelnen 'line'-Parameter, wie die 'tim.append(float(s1))', von der ursprünglichen 'def animation(i):' zu trennen und sie hinter dem 'line'-Auslesen des Bluetooth-Moduls zu platzieren.

Damit habe ich zwei von einander getrennten Modulen, die nacheinander gestartet werden können.
Das Ergebnis ist der unten stehende Code, der zwar, wie ich wollte, läuft, jedoch mit einem unangenehmen Schönheitsfehler, der m. E. mit der Paythonista oder IOS zusammenhängt und ich bis jetzt keine Lösung dafür gefunden habe.

Erstmal der Code:

Code: Alles auswählen

# coding: utf-8

# https://forum.omz-software.com/topic/2846/simpler-way-to-use-the-bluetooth-cb-module

# Sending the character 'H' to an HM-10 BLE module
# Module Name 'HM-10-BLE’
# Module Service UUID 'FFE1'
# Module Characteristics UUID 'FFE0'
#-----------
import random
import datetime
#-----------
import cb
import sound
import time
import struct
import console

import matplotlib.pyplot as plt
import matplotlib.animation as animation
from matplotlib import style
console.set_color()

style.use('fivethirtyeight')

fig = plt.figure()
ax1 = fig.add_subplot(1,1,1)

tz = bytearray(b'')
zle =''
azle = ''
bt = ''
line = ''
x = 0
sp = 0
titel =''
tim = []
tc0 = []
tc1 = []
tx0 = []
tx1 = []
sol = []
ist = []
hot = []
fan = []
ovn = []
reflow = []

def animate(i):
#	print('animate(i)')
	ax1.clear()
	ax1.plot(tim, hot, 'r', linewidth=0.1, label='Heizung/B/')
	ax1.plot(tim, fan, 'b', linewidth=0.1, label='Ventilator/B/')
	ax1.plot(tim, ovn, linewidth=0.5, label='Ofen-Temp.')
	ax1.plot(tim, tc0, linewidth=2.5, label='TC0-links')
	ax1.plot(tim, tc1, linewidth=2.5, label='TC1-rechts')
	ax1.plot(tim, sol, linewidth=2.5, label='Soll-Temp.')
	ax1.plot(tim, ist, linewidth=2.5, label='Ist-Temp.')
	ax1.plot(tim, tx0, linewidth=2.5, label='ExTC2')
	ax1.plot(tim, tx1, linewidth=2.5, label='ExTC3')
	ax1.plot(tim, reflow, linewidth=1.5, label='Schmelzpunkt')
	plt.xlabel('Zeit [s]', fontsize=10)	# Bezeichnung der X-Achse
	plt.ylabel('Temperatur [C]', fontsize=10)	# Bezeichnung der Y-Achse
	plt.title(titel, fontsize=12)	# Plot-Titel
	plt.legend(loc=2, prop={'size': 8})	# Legende einblenden
#	plt.xlim(0,380)
#	plt.ylim(0,250)
	plt.xticks([0,20,40,60,80,100,120,140,160,180,200,220,240,260,280,300,320,340,360],fontsize=10)
     #,[0,20,40,60,80,100,120,140,160,180,200,220,240,260,280,300,320,340,360])
	plt.yticks([0,25,50,75,100,125,150,175,200,225,250],fontsize=10)
     #,[0,25,50,75,100,125,150,175,200,225,250])


class MLT_BT05_Manager (object):
	def __init__(self):
		self.peripheral = None
#		print('\n1: Init')

	def did_discover_peripheral(self, p):
		if p.name == 'MLT-BT05' and not self.peripheral:
#			print('2: Discovered ' + p.name)
			self.peripheral = p
			cb.connect_peripheral(p)

	def did_connect_peripheral(self, p):
#		print('3: Connected Peripheral ' + p.name)
		p.discover_services()

	def did_fail_to_connect_peripheral(self, p, error):
		print('Failed to connect: %s' % (error,))

	def did_disconnect_peripheral(self, p, error):
		self.peripheral = None

	def did_discover_services(self, p, error):
		#x = 0
		for s in p.services:
			#x = x+1
			if s.uuid =='FFE0':
				p.discover_characteristics(s)

	def did_discover_characteristics(self, s, error):
		for c in s.characteristics:
			if c.uuid == 'FFE1':
				self.peripheral.set_notify_value(c, True)

	#def did_write_value(self, c, error):
		#print('14:')

	def did_update_value(self, c, error):
		global sp
		global tz
		global x
		global zle
		global azle
		global titel
		bt = (c.value) # <class 'bytes'>
		if bt[0:2] != b'\r\n':
			tz += bt
		else:
			zle = tz
			tz = bt
#			print('zle=', zle)
			azle = (zle.decode('ascii'))
#			print('azle=', azle)
			line = azle[2:]
#			print('line =', line, len(line))
			if line != []:
#				print('ANI=',line) #-Test-Ausgabe, ob eine line übergeben wurde
#				ab hier die Interpretation des line-Inhaltes zum Aufbau der Grafik
				if len(line) == 39:
					titel = line
					sp = 217
				if len(line) == 48:
					titel = line
					sp = 217
				if len(line) == 47:
					titel = line
					sp = 136
					if 'AMTECH' in line: sp = 217
				if len(line) == 44:
					titel = line
					sp = 183
				if len(line) == 75: # Log-Daten, Zeit, Temperaturen usw.
					x = x + 1
					tline = line[0:67]
#					print(tline)
					if len(tline) > 1:
						s1, s2, s3, s4, s5, s6, s7, s8, s9, s10  = tline.split(',')
						tim.append(float(s1))
						tc0.append(float(s2))
						tc1.append(float(s3))
						tx0.append(float(s4))
						tx1.append(float(s5))
						sol.append(float(s6))
						ist.append(float(s7))
						hot.append(float(s8))
						fan.append(float(s9))
						ovn.append(float(s10))
						reflow.append(float(sp))
						#print(sp,titel,tim,tc0,tc1)

#while True:
	
# 	Initialisiere Bluetooth
mngr = MLT_BT05_Manager()
cb.set_central_delegate(mngr)
#	print('Scanning for peripherals...')
cb.scan_for_peripherals()
while True:
	for i in range (100):
		animation.FuncAnimation(fig, animate,interval=10000)
	plt.show()
# Definiere Animation - jede 5 Sekunden wird Methode animate aufgerufen
#ani = animation.FuncAnimation(fig, animate, interval=5000)
# starte Animation, soll unendlich (bis zum Abbrechen) laufen
#plt.show()
Ob ich für die Animation den Aufruf 'animation.FuncAnimation(fig, animate,interval=10000)' oder 'animate(0)' benutze, bleibt das Ergebnis gleich.

Egal, wie ich die Programme aufrufe, wird alle paar Sekunden ein neuer Plot in der Console dargestellt, zwar verlängert mit den neuen dazugelesenen Daten, aber insgesamt unbefriedigend. Ich könnte zwar vorläufig damit leben, wenn die Gefahr nicht bestünde, dass das Programm mitten drin aufgrund zu hoher Speicherbelegung(?) abstürzt.
Das passiert mit meinem alten Ipad mini mit seinem freien 4,1 GB speicher, jedoch mit dem iphone 8-Plus nicht.
Ich habe die Anzahl der erzeugten Einzelnplot während eines 6 minutigen Temperaturprofils gezählt. 69 Stück!

Seltsamerweise passiert das in einem PC oder MAC nicht. Der ganze Diagrammaufbau von Anfang bis Ende geschieht in einem einzigen Plot (Figure).

Irgendeine Idee?
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Wenn ich mich mal kurz selbst zitieren darf:

ich habe aber rausgefunden, woran es liegt. Jeder Aufruf von plt.show() produziert ein Bild in der Konsole. Folgender Code ist auch bei mir animiert:
...
Wenn dir diese Form der Ausgabe reicht, dann lies deine Daten in der while Schleife ein, und plotte halt jedes mal neu.


matplotlib KANN keine Animation unter Pythonista. Es wird einfach IMMER ein neues Bild erzeugt, und einfach ausgegeben. Unter macOS ist das natuerlich anders, da bringt auch dein FuncAnimation dann etwas.

Wenn das fuer dich nicht funktioniert, habe ich dir auch schon Hinweise gegeben:

- schau in das verlinkte Backend aus einem meiner frueheren Posts. Das erlaubt Animation, und greift dann zurueck auf die native iOS rendering Moeglichkeiten. Das Projekt scheint aber in den Kinderschuhen zu stecken, und ist ungewartet.
- schreib dir die Darstellung selbst. Das ist je nach Anspruch einfacher, als das Backend zu erweitern, weil du da matplotlib UND Pythonista Scene Graph Kenntnisse brauchst. Kann aber auch einfacher sein, weil das Backend viele Dinge die matplotlib schon kann (wie zB das ganze Skalierungs-Thema) beherrscht.
- last but not least frag im Pythonista-Forum nach, ob du ggf. eine Funktion nutzen kannst, die Konsole zu loeschen und dadurch die alten Frames loszuwerden. Oder ggf. eine Einstellung, welche die Historie-Laenge beschraenkt, oder sowas.
Dymo
User
Beiträge: 14
Registriert: Donnerstag 30. August 2018, 04:50

@__deets__:
Vielen Dank __deets__. Ich muss zugeben, dass ich Deine Anregungen nicht konzentriert genug gelesen hatte und deine Aussagen nicht tiefsinnig genug aufgenommen hatte. Kein Wunder, dass meine Frau mir vorwirft, dass ich manchmal aus lauter Eile nicht verstehe, was ich lese ;)
Kein wunder, dass Du aufgeben wolltest. Jetzt glaube jetzt bin ich d'accord.
Ich war vorhin auch auf die Idee gekommen, irgendwie herauszufinden, wie man aus dem Programm her den Inhalt der Console löscht.
Antworten