Creating a state machine with changing frames - is it possible?

Alright, I’m about to rip my hair out. I’m working to make a simple application on my Raspberry Pi that changes screens with each change in state (I’m using a state machine). Is doing this even possible?

For example: User sees starting screen, pushes button which places them in state machine. Each state in the state machine has an exit, such as “button pushed,” or “input received from Raspberry pi”, and then it goes to a new state with a new screen.

Here’s what I have:

···

#state.py

class State(object):

def init(self):

print(‘Processing current state:’, str(self))

def on_event(self, event):

pass

def repr(self):

return self.str()

def str(self):

return self.class.name


#my_states.py

from state import State

import time

import wx

import RPi.GPIO as GPIO

BUTTON = 40

PHOTO_TRANSISTOR = 37

RELAY = 38

LED = 12

GPIO.setmode(GPIO.BOARD)

GPIO.setwarnings(False)

GPIO.setup(BUTTON, GPIO.IN)

GPIO.setup(PHOTO_TRANSISTOR, GPIO.IN)

GPIO.setup(RELAY, GPIO.OUT)

GPIO.setup(LED, GPIO.OUT)

GPIO.output(RELAY, GPIO.LOW)

GPIO.output(LED, GPIO.HIGH)

class WelcomeState(State):

def on_event(self,event):

print(event)

png = wx.Image(‘2 insert card.png’, wx.BITMAP_TYPE_ANY).ConvertToBitmap() -----This is where my problem is

wx.StaticBitmap(self, -1, png, (10,5), (png.GetWidth(), png.GetHeight()))

if (GPIO.input(BUTTON) == True):

return InsertCardState()

else:

return WelcomeState() -------Also trying to figure out how to simply stay in the state until input is received, doing this keeps looping it and it gets stuck

class InsertCardState(State):

def on_event(self, event):

print(event)

if (GPIO.input(BUTTON) == True):

return FillState()

return InsertCardState()

class FillState(State):

def on_event(self, event):

print(event)

runWaterPump()

return ThankYouState()

class ThankYouState(State):

def on_event(self, event):

print(event)

return WelcomeState()

def runWaterPump():

runTime = 10

time.sleep(runTime)

GPIO.output(RELAY, GPIO.HIGH)


#state_machine.py

from my_states import WelcomeState

class StateMachine(object):

def init(self):

self.state = WelcomeState()

def on_event(self, event):

self.state = self.state.on_event(event)


#main.py

#!/usr/bin/env python

import wx

import images

import time

import threading

from threading import Thread

from multiprocessing.pool import ThreadPool

from state_machine import StateMachine

from state import State

from wx.lib.pubsub import pub

class Main(wx.Frame):

def init(self, parent, title):

super(Main, self).init(parent, title=title, size=(300,250))

self.Move((0,0))

self.Maximize()

self.Show()

self.bitmap1 = wx.StaticBitmap(self, -1, wx.Bitmap(‘1 welcome.png’), (0,0))

self.welcome_button = wx.Button(self, label=“WELCOME”)

self.Bind(wx.EVT_BUTTON, self.startSystem, self.welcome_button)

def startSystem(self,event):

thread = Thread(target = runSystem, args = (self,))

thread.start()

def runSystem(arg):

print(‘runSystem’)

global systemEvent

machine = StateMachine()

true_on = True

while true_on:

machine.on_event(machine) ----This main code all works, it just gets stuck once it gets to the first state

if name == ‘main’:

app = wx.App()

Main(None, title=‘Tide Detergent Station’)

app.MainLoop()

Consider using a wx.Notebook with multiple pages to display different “screens” - it is simple to switch between notebook pages.

Also, consider the pigpio library on the Raspberry Pi - it’s included with recent Raspbian versions and is more convenient than

RPi.GPIO.

Yes, it is all possible.

···

On Friday, April 6, 2018 at 9:23:39 AM UTC-6, Karina Coug wrote:

Alright, I’m about to rip my hair out. I’m working to make a simple application on my Raspberry Pi that changes screens with each change in state (I’m using a state machine). Is doing this even possible?

For example: User sees starting screen, pushes button which places them in state machine. Each state in the state machine has an exit, such as “button pushed,” or “input received from Raspberry pi”, and then it goes to a new state with a new screen.

Here’s what I have:


#state.py

class State(object):

def init(self):

print(‘Processing current state:’, str(self))

def on_event(self, event):

pass

def repr(self):

return self.str()

def str(self):

return self.class.name


#my_states.py

from state import State

import time

import wx

import RPi.GPIO as GPIO

BUTTON = 40

PHOTO_TRANSISTOR = 37

RELAY = 38

LED = 12

GPIO.setmode(GPIO.BOARD)

GPIO.setwarnings(False)

GPIO.setup(BUTTON, GPIO.IN)

GPIO.setup(PHOTO_TRANSISTOR, GPIO.IN)

GPIO.setup(RELAY, GPIO.OUT)

GPIO.setup(LED, GPIO.OUT)

GPIO.output(RELAY, GPIO.LOW)

GPIO.output(LED, GPIO.HIGH)

class WelcomeState(State):

def on_event(self,event):

print(event)

png = wx.Image(‘2 insert card.png’, wx.BITMAP_TYPE_ANY).ConvertToBitmap() -----This is where my problem is

wx.StaticBitmap(self, -1, png, (10,5), (png.GetWidth(), png.GetHeight()))

if (GPIO.input(BUTTON) == True):

return InsertCardState()

else:

return WelcomeState() -------Also trying to figure out how to simply stay in the state until input is received, doing this keeps looping it and it gets stuck

class InsertCardState(State):

def on_event(self, event):

print(event)

if (GPIO.input(BUTTON) == True):

return FillState()

return InsertCardState()

class FillState(State):

def on_event(self, event):

print(event)

runWaterPump()

return ThankYouState()

class ThankYouState(State):

def on_event(self, event):

print(event)

return WelcomeState()

def runWaterPump():

runTime = 10

time.sleep(runTime)

GPIO.output(RELAY, GPIO.HIGH)


#state_machine.py

from my_states import WelcomeState

class StateMachine(object):

def init(self):

self.state = WelcomeState()

def on_event(self, event):

self.state = self.state.on_event(event)


#main.py

#!/usr/bin/env python

import wx

import images

import time

import threading

from threading import Thread

from multiprocessing.pool import ThreadPool

from state_machine import StateMachine

from state import State

from wx.lib.pubsub import pub

class Main(wx.Frame):

def init(self, parent, title):

super(Main, self).init(parent, title=title, size=(300,250))

self.Move((0,0))

self.Maximize()

self.Show()

self.bitmap1 = wx.StaticBitmap(self, -1, wx.Bitmap(‘1 welcome.png’), (0,0))

self.welcome_button = wx.Button(self, label=“WELCOME”)

self.Bind(wx.EVT_BUTTON, self.startSystem, self.welcome_button)

def startSystem(self,event):

thread = Thread(target = runSystem, args = (self,))

thread.start()

def runSystem(arg):

print(‘runSystem’)

global systemEvent

machine = StateMachine()

true_on = True

while true_on:

machine.on_event(machine) ----This main code all works, it just gets stuck once it gets to the first state

if name == ‘main’:

app = wx.App()

Main(None, title=‘Tide Detergent Station’)

app.MainLoop()