Wir haben momentan 8 Module mit 14 Stellen an denen die Weiche eingesetzt wird.
Eine davon in /lib (umal.py), der Rest unter /terkin. Keine davon in /dist-packages. 3rd party ist also momentan gar kein Problem.
try / except würde fast überall funktionieren. Dagegen sprechen mAn zwei Dinge: mir widerstrebt es irgendwie, ein Programm bewusst in einen Fehler laufen zu lassen (da bin ich vermutlich altmodisch ) und das Konstrukt wird doof, wenn wir mal einen dritte Hardware unterstützen wollen.
Wenn das keine Hinderungsgründe sind, bau ich das gerne auf try / except um.
Alternativvorschlag: wir bauen ein Modul nur mit den Platformeigenschaften und importieren das bei Bedarf. Das ist vermutlich ‘billiger’ als sys oder try und leichter zu warten und zu lesen.
Nein, so war das nicht gemeint. try / except sehe ich nur als Fallback für Fälle, wo das Plattformeigenschaftsmodul nicht zur Verfügung steht oder es ungut ist, es zu importieren.
Ja, genau so dachte ich mir das mit der class PlatformInfo aus umal.py. Entweder man
importiert und instanziiert die Klasse (erneut), wo man sie braucht, oder man greift wahlweise auf
bootloader.platform_info über die globale Variable bootloader oder eben auf
das schon bekannte self.application_info.platform_info zurück.
from umal import MicroPythonPlatform
# Keep track of time since boot.
from terkin.util import GenericChronometer, PycomChronometer
if bootloader.platform_info.vendor == MicroPythonPlatform.Pycom:
_chrono = PycomChronometer()
else:
_chrono = GenericChronometer()
nicht?
[main.py] INFO: Starting logging
Traceback (most recent call last):
File "main.py", line 21, in <module>
File "terkin/logging.py", line 13, in <module>
NameError: name 'bootloader' isn't defined
bootloader ist doch global?
Ich gestehe, das ich mich mit dem objektorientierten manchmal etwas schwer tue. Dazu bin ich den prozeduralen Sprachen zu sehr verhaftet.
#from umal import MicroPythonPlatform
global bootloader
# Keep track of time since boot.
from terkin.util import GenericChronometer, PycomChronometer
if bootloader.platform_info.vendor == MicroPythonPlatform.Pycom:
_chrono = PycomChronometer()
else:
_chrono = GenericChronometer()
führt zu:
[main.py] INFO: Starting logging
Traceback (most recent call last):
File "main.py", line 21, in <module>
File "terkin/logging.py", line 14, in <module>
NameError: name 'bootloader' isn't defined
Hast Du ein Indiz dafür, dass der Bootloader zu diesem Zeitpunkt bereits angefahren wurde? z.B. die Log-Nachricht [boot.py] INFO: Starting "umal" bootloader müsste da schon zu sehen gewesen sein.
Benutze doch hier im konkreten Fall kurzerhand doch einfach immer den GenericChronometer. Das aktuelle Pycom-Firmware-Release kennt mindestens die Primitiven time.ticks_ms() sowie time.ticks_diff(), daher sollte dieser auch genauso gut mit Pycom funktionieren.
@Andreas - bei mir ist machine.freq() ein INT. Ist das beim pyboard anders?
Sonst verstehe ich den Sinn der Weiche in device.py nicht.
if self.application_info.platform_info.vendor == MicroPythonPlatform.Pycom:
frequency = machine.freq() / 1000000
else:
frequency = machine.freq()[0] / 1000000
Ja, dort ist das ein Quadrupel aus core- und bus frequencies. Die Weiche muss hier wohl noch entsprechend aufgemöbelt werden, falls das bei Dir grade hängt. Entweder über die platform_info Konstanten oder per Typüberprüfung à la
frequency = machine.freq()
if type(frequency) is tuple:
frequency = frequency[0]
frequency = frequency / 1000000
So wäre es universeller und agnostischer gegenüber der Plattformweiche – at all ;].
Letzte Frage für heute. Der I2C-Bus ist bei Vanilla etwas anders als bei Pycom. Gibts da beim Pyboard noch was anderes? Sonst würde das so aussehen (core.py):
heißen? Das erstere funktioniert bei mir nicht, das letztere schon. Da ich aber schon mal etwas wirre Problemem mit dem PATH hatte, wollte ich nachfragen, bevor ich was fixe, was kein Problem ist.
Hmm, habe gerade bemerkt, das onewire Standardmäßig in uPy enthalten ist. Vermutlich ist das das Problem.
Gibts einen Grund, warum wir eine andere Version in dist-packages haben?
Ja, beim Genuine MicroPython (1.11) mittlerweile bereits auch in einer “guten” Variante, bei der die Timing-kritischen Dinge in C implementiert sind [1].
Das ist leider bei Pycom MicroPython (1.9.4) [2] noch nicht der Fall. Der hier verwendete Treiber ist [3] und selbst der ist schrottig, so dass wir auf eine bessere Variante von [4] ausgewichen sind.
Warum ist denn die Logik für den Start des mode- und http-server invertiert?
def start_services(self):
# Start UDP server for pulling device into maintenance mode.
if self.settings.get('services.api.modeserver.enabled', False):
try:
self.start_modeserver()
except Exception as ex:
log.exc(ex, 'Starting mode server failed')
# Start HTTP server
if self.settings.get('services.api.http.enabled', False):
try:
self.start_httpserver()
except Exception as ex:
log.exc(ex, 'Starting HTTP server failed')