Code Documentation

Hottop Interface

This is the primary class that you will interact with when building applications for the Hottop roaster. This class will automatically spawn a threaded instance of the control process which will handle the core of the operations against the roaster.

class pyhottop.pyhottop.Hottop[source]

Object to interact and control the hottop roaster.

Returns:Hottop instance
_autodiscover_usb()[source]

Attempt to find the serial adapter for the hottop.

This will loop over the USB serial interfaces looking for a connection that appears to match the naming convention of the Hottop roaster.

Returns:string
_callback(data)[source]

Processor callback to clean-up stream data.

This function provides a hook into the output stream of data from the controller processing thread. Hottop readings are saved into a local class variable for later saving. If the user has defined a callback, it will be called within this private function.

Parameters:data (dict) – Information from the controller process
Returns:None
_derive_charge(config)[source]

Use a temperature window to identify the roast charge.

The charge will manifest as a sudden downward trend on the temperature. Once found, we save it and avoid overwriting. The charge is needed in order to derive the turning point.

Parameters:config (dict) – Current snapshot of the configuration
Returns:None
_derive_turning_point(config)[source]

Use a temperature window to identify the roast turning point.

Turning point relies on the charge being set first. We use the rolling 5-point window to measure slope. If we show a positive trend after the charge, then the temperature has begun to turn.

Parameters:config (dict) – Current snapshot of the configuration
Returns:None
_init_controls()[source]

Establish a set of base controls the user can influence.

Returns:None
_logger()[source]

Create a logger to be used between processes.

Returns:Logging instance.
add_roast_event(event)[source]

Add an event to the roast log.

This method should be used for registering events that may be worth tracking like first crack, second crack and the dropping of coffee. Similar to the standard reading output from the roaster, manually created events will include the current configuration reading, time and metadata passed in.

Parameters:event (dict) – Details describing what happened
Returns:dict
connect(interface=None)[source]

Connect to the USB for the hottop.

Attempt to discover the USB port used for the Hottop and then form a connection using the serial library.

Returns:bool
Raises:SerialConnectionError
drop()[source]

Preset call to drop coffee from the roaster via thread signal.

This will set the following configuration on the roaster: - drum_motor = 0 - heater = 0 - solenoid = 1 - cooling_motor = 1 - main_fan = 10

In order to power-off the roaster after dropping coffee, it’s best to use the shutdown method. It’s assumed that cooling will occur for 5-10 minutes before shutting down.

Returns:None
end()[source]

End the roaster control process via thread signal.

This simply sends an exit signal to the thread, and shuts it down. In order to stop monitoring, call the set_monitor method with false.

Returns:None
get_cooling_motor()[source]

Get the cooling motor config.

Returns:None
get_current_config()[source]

Get the current running config and state.

Returns:dict
get_drum_motor()[source]

Get the drum motor config.

Returns:None
get_fan()[source]

Get the fan config.

Returns:int [0-10]
get_heater()[source]

Get the heater config.

Returns:int [0-100]
get_main_fan()[source]

Get the main fan config.

Returns:None
get_monitor()[source]

Get the monitor config.

Returns:None
get_roast()[source]

Get the roast information.

Returns:list
get_roast_properties()[source]

Get the roast properties.

Returns:dict
get_roast_time()[source]

Get the roast time.

Returns:float
get_serial_state()[source]

Get the state of the USB connection.

Returns:dict
get_simulate()[source]

Get the simulation status.

Returns:bool
get_solenoid()[source]

Get the solenoid config.

Returns:None
reset()[source]

Reset the internal roast properties.

Returns:None
set_cooling_motor(cooling_motor)[source]

Set the cooling motor config.

Parameters:cooling_motor (bool) – Value to set the cooling motor
Returns:None
Raises:InvalidInput
set_drum_motor(drum_motor)[source]

Set the drum motor config.

Parameters:drum_motor (bool) – Value to set the drum motor
Returns:None
Raises:InvalidInput
set_fan(fan)[source]

Set the fan config.

Parameters:fan (int [0-10]) – Value to set the fan
Returns:None
Raises:InvalidInput
set_heater(heater)[source]

Set the heater config.

Parameters:heater (int [0-100]) – Value to set the heater
Returns:None
Raises:InvalidInput
set_interval(interval)[source]

Set the polling interval for the process thread.

Parameters:interval (int or float) – How often to poll the Hottop
Returns:None
Raises:InvalidInput
set_main_fan(main_fan)[source]

Set the main fan config.

Parameters:main_fan (int [0-10]) – Value to set the main fan
Returns:None
Raises:InvalidInput
set_monitor(monitor)[source]

Set the monitor config.

This module assumes that users will connect to the roaster and get reading information _before_ they want to begin collecting roast details. This method is critical to enabling the collection of roast information and ensuring it gets saved in memory.

Parameters:monitor (bool) – Value to set the monitor
Returns:None
Raises:InvalidInput
set_roast_properties(settings)[source]

Set the properties of the roast.

Parameters:settings (dict) – General settings for the roast setup
Returns:None
Raises:InvalidInput
set_simulate(status)[source]

Set the simulation status.

Parameters:status (bool) – Value to set the simulation
Returns:None
Raises:InvalidInput
set_solenoid(solenoid)[source]

Set the solenoid config.

Parameters:solenoid (bool) – Value to set the solenoid
Returns:None
Raises:InvalidInput
start(func=None)[source]

Start the roaster control process.

This function will kick off the processing thread for the Hottop and register any user-defined callback function. By default, it will not begin collecting any reading information or saving it. In order to do that users, must issue the monitor/record bit via set_monitor.

Parameters:func (function) – Callback function for Hottop stream data
Returns:None

Control Process

Due to the nature of continuously needing to poll the serial interface, a thread was required to handle interactions with the serial interface. It’s possible to use the multiprocessing module to handle this work, but when using this library inside of web server technology, multiprocessing often causes issues. Vanilla threads were used here to avoid interaction problems with co-routine or eventlet-based libraries.

class pyhottop.pyhottop.ControlProcess(conn, config, q, logger, callback=None)[source]

Primary processor to communicate with the hottop directly.

Parameters:
  • conn (Serial instance) – Established serial connection to the Hottop
  • config (dict) – Initial configurations settings
  • q (Queue instance) – Shared queue to interact with the user interface
  • logger (Logging instance) – Shared logger to keep continuity
  • callback (function) – Optional callback function to stream results
Returns:

ControlProces instance

_generate_config()[source]

Generate a configuration that can be sent to the Hottop roaster.

Configuration settings need to be represented inside of a byte array that is then written to the serial interface. Much of the configuration is static, but control settings are also included and pulled from the shared dictionary.

Returns:Byte array of the prepared configuration.
_read_settings(retry=True)[source]

Read the information from the Hottop.

Read the settings from the serial interface and convert them into a human-readable format that can be shared back to the end-user. Reading from the serial interface will occasionally produce strange results or blank reads, so a retry process has been built into the function as a recursive check.

Returns:dict
_send_config()[source]

Send configuration data to the hottop.

Returns:bool
Raises:Generic exceptions if an error is identified.
_valid_config(settings)[source]

Scan through the returned settings to ensure they appear sane.

There are time when the returned buffer has the proper information, but the reading is inaccurate. When this happens, temperatures will swing or system values will be set to improper values.

Parameters:settings (dict) – Configuration derived from the buffer
Returns:bool
_validate_checksum(buffer)[source]

Validate the buffer response against the checksum.

When reading the serial interface, data will come back in a raw format with an included checksum process.

Returns:bool
_wake_up()[source]

Wake the machine up to avoid race conditions.

When first interacting with the Hottop, the machine may not wake up right away which can put our reader into a death loop. This wake up routine ensures we prime the roaster with some data before starting our main loops to read/write data.

Returns:None
drop()[source]

Register a drop event to begin the cool-down process.

Returns:None
run()[source]

Run the core loop of reading and writing configurations.

This is where all the roaster magic occurs. On the initial run, we prime the roaster with some data to wake it up. Once awoke, we check our shared queue to identify if the user has passed any updated configuration. Once checked, start to read and write to the Hottop roaster as long as the exit signal has not been set. All steps are repeated after waiting for a specific time interval.

There are also specialized routines built into this function that are controlled via events. These events are unique to the roasting process and pre-configure the system with a configuration, so the user doesn’t need to do it themselves.

Returns:None
shutdown()[source]

Register a shutdown event to stop interacting with the Hottop.

Returns:None