State

Appliance States are the entities which build up the non deterministic state machine.

Take a curtain as an example.

A curtain could be Closed for many different reasons:
  • it could be Closed because someone forced it to be closed

  • or it could be Closed because the sun is hitting the window and the system closes it.

It is up to the non deterministic state machine design decide which are the events that allow a Closed curtain to become Opened:
  • a state called forced.Closed receiving the sun is not hitting the window anymore event will result in the same forced.Closed state.

  • a state called Closed receiving the sun is not hitting the window anymore event will result in a new Opened state.

Hint

You could not say which will be the next Appliance State, upon reception of an event, unless you know exactly the internal state of an Appliance State.

class home.appliance.curtain.outdoor.state.State(events: Iterable[home.Event] = None, events_disabled: Iterable[home.Event] = None)
>>> import home
>>> state = home.appliance.curtain.outdoor.state.opened.State()
>>> state.compute()
'Opened'
>>> state = state.next(home.appliance.curtain.event.forced.Event.Closed)
>>> state.compute()
'Forced Closed'
>>> state = state.unforce()
>>> state.compute()
'Opened'
>>> state = state.next(home.event.sun.twilight.civil.Event.Sunset)
>>> state.compute()
'Closed'
>>> state = state.next(home.event.sun.twilight.civil.Event.Sunrise)
>>> state.compute()
'Opened'

From Forced States to other States

When the system changes the State of, as an example, a curtain Appliance it will put it in a non forced State (opened or closed).

When you push the down button you will force close the curtain.

When you push the up button you will force open the curtain.

When is the curtain unlocked from a forced state?

Hint

Supposing that the system does, most of the time, the things you will do; it could be said that the Appliance State could be forced only if you disagree with the system rules.

A forced state could be automatically unlocked when you and the system agree again.

Example

The sun is hitting the window and the appliance non deterministic state machine says the curtain should be in a Closed state. But you need it to be opened and pressing a button you open it in a Forced Opened state. Few minutes later the wind starts blowing strong and the system says that the curtain should be in a Opened state. Now you and the system agree and the curtain state can be moved from a Forced Opened state to an Opened state.

Hint

Every Event changing the state could unlock a forced state. But sometimes Events comes so often, and make the state change so often, that is better if they will not unlock a state. Is up to the non deterministic state machine design decide which are the events which will reset a forced state.

Event Class

home.Event: TypeVar = TypeVar('home.Event')

One of:

  • int

  • float

  • str

  • home.Enum

  • home.appliance.light.event.hue.Event

  • home.appliance.light.event.brightness.Event

  • home.appliance.light.event.saturation.Event

  • home.appliance.light.event.temperature.Event

  • home.appliance.light.show.cycles.Event

  • home.appliance.light.show.ending_brightness.Event

  • home.appliance.light.show.ending_hue.Event

  • home.appliance.light.show.period.Event

  • home.appliance.light.show.starting_brightness.Event

  • home.appliance.light.show.starting_hue.Event

  • home.appliance.light.event.lux_balancing.brightness.Event

  • home.appliance.light.event.circadian_rhythm.brightness.Event

  • home.appliance.light.event.circadian_rhythm.hue.Event

  • home.appliance.light.event.circadian_rhythm.saturation.Event

  • home.appliance.light.event.circadian_rhythm.temperature.Event

  • home.appliance.sound.player.event.volume.Event

  • home.appliance.sound.player.event.sleepy_volume.Event

  • home.appliance.sound.player.event.playlist.Event

  • home.appliance.sound.player.event.forced.circadian_rhythm.playlist_a.Event

  • home.appliance.sound.player.event.forced.circadian_rhythm.playlist_b.Event

  • home.appliance.sound.player.event.forced.circadian_rhythm.playlist_c.Event

  • home.appliance.sound.player.event.fade_in.volume.Event

  • home.appliance.sound.player.event.fade_in.playlist.Event

  • home.appliance.sound.player.event.fade_out.volume.Event

  • home.appliance.sound.player.event.fade_out.playlist.Event

Callable Class

class home.appliance.Callable(**kwargs: Dict[str, home.appliance.State])

A single transaction used to build up a non deterministic state machine.

abstract run(event: home.Event, state: home.appliance.State) home.appliance.State

Do a transaction. From given state, processing given event, choose a final state.

Parameters
  • event – An event to be processed

  • state – A state from which transaction starts

Returns

the input state or another one (from those used to build up the transaction)

get_new_state(old_state: home.appliance.State, new_state_key: str) home.appliance.State

Get the internal named new_state_key state . Build it using events taken from given old_state.

Parameters
  • old_state – Take events from this state when creating new state

  • new_state_key – Choose the internal state using this name

Returns

The new choose state instance.

compute_new_state(old_state: home.appliance.State, new_state_key: str, events: Iterable[home.Event])

Get the internal named new_state_key state . Build it using events taken from given old_state, excluding those specified in given events.

Parameters
  • old_state – Take events from this state when creating new state

  • new_state_key – Choose the internal state using this name

  • events – Exclude thi events when creating new state.

Returns

The new choose state instance.

State Class

class home.appliance.State(events: Iterable[home.Event] = None, events_disabled: Iterable[home.Event] = None)

An abstract Appliance State object.

property events: Iterable[home.Event]

All Events already notified to the Appliance

property events_disabled: Iterable[home.Event]

All Events disabled in this state machine

is_enabled(event: home.Event) bool

Are event of given event type enabled?

Parameters

event – home.Event

Returns

bool

disable(event: home.Event)

Disable processing for events of the same type in the state machine.

Parameters

event – home.Event

enable(event: home.Event)

Enable processing for events of the same type in the state machine.

Parameters

event – home.Event

classmethod make(events: Iterable[home.Event], events_disabled: Iterable[home.Event] = None) home.appliance.State
Parameters
  • events – to be processed by a new State

  • events_disabled – list of events which will not be updated!

Returns

a brand new State

next(event: home.Event) home.appliance.State
Parameters

event – to be processed by this State

Returns

a brand new State (if necessary)

compute() str
Returns

a str representation of this state

force(value: str) home.appliance.State
Parameters

value – a value in forced Event Enum values

Returns

the related forced State

unforce() home.appliance.State
Returns

a non forced State