Python Advanced (2023-10-24 - 2023-10-26)

Day 1

Python Basics Recap

All optional. But we should not miss the central points like Python’s referencing scheme, im/mutability, memory management, typing. And iteration of course 😎. Everything’s an object, alas.

The Very Basics

Exercise time …

range(), And Iteration In General

Modules

Group Project Kickoff

  • Draw “Data Logger” sketch

  • Sensor classes intro

  • Main loop ⟶ application, simply printing to stdout

Object Oriented Programming

From Object Oriented Programming

Day 2

Leftovers From Yesterday

Miscellaneous

Object Oriented Programming, Continued

From Object Oriented Programming

Group Project, OO-ified

  • FileSensor

  • CSVSink

  • AcquisitionLoop

Bring them live …

Test Driven Development

Object Oriented Programming, Continued

  • Inheritance

    Apply inheritance

    • Create Sensor base class (test first)

    • assert being-a Sensor before entering main loop

  • Abstract Base Classes (abc), And Duck Typing

    • Require Sensor to be-a abc.ABC (test first)

  • Put all sensor implementations under an abstract base class, sensor.Sensor.

Decorator Toolcase: *args, **kwargs

Day 3

Morning Greeting

Decorator Toolcase, Continued (Including Function Scoping and global)

Multithreading

Exercises

Sensor Implementation That Receives UDP Datagrams

  • Datagrams contain temperature in millcelsius (just like FileSensor)

  • Look into acquisition_loop_utils.py for how to receive datagrams on a port

  • Acquisition rate does ont necessarily match datagram rate. It might well be that

    • Datagrams are received much faster (10ms, for example) than the acquisition loop acquires measurements (1s interval, for example). Samples gather up inside the sensor (roughly 100 samples per measurement with the above rates).

      In this case (multiple samples available at the time sensor.get_temperature() is called) a call to sensor.get_temperature() must

      • compute the average across available samples

      • remove the gathered samples to make room for new incoming data

    • Datagrams are received at a slower rate than the loop acquires. In this case there is nothing available to return from sensor.get_temperature(). To overcome that,

      • If a measurement from a previous measurement is available, return that

      • If no measurement has yet been made, raise an exception

  • To not drop any packets while the main acquisition loop is busy doing other things (block on file IO, for example, or wait for another sensor to complete its measurement), the sensor implementation must spawn a thread, internally, that does the network communication.

    In fact, the whole point of the exercise is to correctly communicate the data to the main (acquisition) thread.

  • Is it possible to TDD that? Try hard.

CompositeSink

  • AcquisitionLoop knows about only one Sink. That is the plan!

  • Create one Sink implementation, CompositeSink, that dispatches write_measurement() onto multiple sinks that it owns

  • Write a test for that, together.

MQTT Sink Implementation

  • Publish measurement dictionary to an MQTT broker

  • Define format of transmitted data

  • TDD?!

Timestamps?

Bring timestamps (datatime.datatime) into the game …

  • Formally define measurement dictionary (test)

  • Wrap sensors dictionary that is used in datalogger.py into a class, say, Sensors.

  • Write a method Sensors.read_measurements() -> Measurements

  • class Measurements is an encapsulation of the raw dictionary that is composed in AcquisitionLoop, and consumed across all Sink implementations.

Data Science

Pandas

NumPy

Error Handling And Recovery

Project Management