Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test script and logs #13

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 50 additions & 50 deletions gameserver.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
import logging as log
from GameStarter.gamestart import GameStarter

logger = log.getLogger()
logger.setLevel(log.DEBUG)

lifeDisplay = False
sound = True #Switch this off if you don't have pyGame
debugMode = False
Expand Down Expand Up @@ -50,21 +53,20 @@ def playSound(filename):
currenttimeout = 30.0
lastgenerated = time.time()
numinstructions = 0
gamestate = 'initserver' #initserver, readytostart, waitingforplayers, initgame, setupround, playround, roundover, hyperspace, gameover
warningsound = None
game_state = {
"stage": 'initserver',
"skip_intro": False
}

#Show when we've connected
def on_connect(mosq, obj, rc):
"""Receive MQTT connection notification"""
if rc == 0:
print("Connected to MQTT")
global gamestate
gamestate = 'readytostart'
log.info("Connected to MQTT")
game_state['stage'] = 'readytostart'
else:
print("Failed - return code is " + rc)
log.error("Failed - return code is " + rc)


def game_exit():
Expand Down Expand Up @@ -98,7 +100,7 @@ def on_message(mosq, obj, msg):
if msg.topic.startswith('command/'):
process_command_message(msg)
nodes = msg.topic.split('/')
print(gamestate + ' - ' + msg.topic + " - " + str(msg.payload))
log.info("message: state=%s, topic:%s payload:%s", game_state['stage'], msg.topic ,msg.payload)
if nodes[0]=='server':
if nodes[1]=='register':
config = json.loads(str(msg.payload))
Expand All @@ -108,12 +110,12 @@ def on_message(mosq, obj, msg):
consoles.append(consoleip)
#set console up for game start
consolesetup = {}
if gamestate in ['readytostart', 'waitingforplayers']:
if game_state['stage'] in ['readytostart', 'waitingforplayers']:
#Still waiting to start
consolesetup['instructions'] = controls.blurb['readytostart']
consolesetup['timeout'] = 0.0
consolesetup['controls'] = {}
print(config['controls'])
log.debug("Controls: %s", config['controls'])
for control in config['controls']:
ctrlid = control['id']
consolesetup['controls'][ctrlid]={}
Expand Down Expand Up @@ -168,11 +170,10 @@ def on_message(mosq, obj, msg):
def receiveValue(consoleip, ctrlid, value):
"""Process a received value for a control"""
global lastgenerated
global gamestate
global numinstructions
global gsIDs
global nextID
if gamestate == 'playround':
if game_state['stage'] == 'playround':
#Check posted value against current targets
matched = False
if 'definition' in currentsetup[consoleip]['controls'][ctrlid]:
Expand Down Expand Up @@ -201,35 +202,37 @@ def receiveValue(consoleip, ctrlid, value):
#Suppress caring about button releases - only important in game starts
if not (currentsetup[consoleip]['controls'][ctrlid]['type'] == 'button' and str(value) == "0"):
playSound(random.choice(controls.soundfiles['wrong']))
elif gamestate == 'setupround':
elif game_state['stage'] == 'setupround':
if 'definition' in currentsetup[consoleip]['controls'][ctrlid]:
currentsetup[consoleip]['controls'][ctrlid]['definition']['value'] = value
elif gamestate in ['readytostart', 'waitingforplayers']:
elif game_state['stage'] in ['readytostart', 'waitingforplayers']:
#button push?
if 'gamestart' in currentsetup[consoleip]['controls'][ctrlid]:
if value:
#Add to list of players
if not consoleip in gsIDs:
# Add to list of players
if consoleip not in gsIDs:
gsIDs[consoleip] = nextID
nextID += 1
#players.append(consoleip)
# players.append(consoleip)
log.debug('Joining the game: %s', consoleip)
gs.push(gsIDs[consoleip])
else:
#remove from list of players
# remove from list of players
if consoleip in gsIDs:
gs.release(gsIDs[consoleip])
#players.remove(consoleip)
#Either way, reset the clock for game start
gamestate = 'waitingforplayers'
# players.remove(consoleip)
log.debug('Leaving the game: %s', consoleip)
# Either way, reset the clock for game start
game_state['stage'] = 'waitingforplayers'
lastgenerated = time.time()

#Define a new set of controls for each client for this game round and send it to them as JSON.
def defineControls():
"""Define a new set of controls for each client for this game round and send it to them as JSON."""
emergency = controls.getEmergency()
print(emergency)
log.info("Controls Emergency: %s", emergency)
for consoleip in players:
print("Defining console " + consoleip)
log.info("Defining console %s", consoleip)
consolesetup={}
consolesetup['instructions']=emergency
consolesetup['timeout'] = currenttimeout
Expand Down Expand Up @@ -301,8 +304,8 @@ def defineControls():
elif ctrltype == 'pin':
ctrldef['value'] = ''
consolesetup['controls'][ctrlid]['type'] = ctrltype
consolesetup['controls'][ctrlid]['definition']=ctrldef
print("Control " + ctrlid + " is " + ctrldef['type'] + ": " + consolesetup['controls'][ctrlid]['name'])
consolesetup['controls'][ctrlid]['definition'] = ctrldef
log.info("New control: id=%s, type=%s, name=%s", ctrlid, ctrldef['type'], consolesetup['controls'][ctrlid]['name'])

currentsetup[consoleip]=consolesetup
client.publish('clients/' + consoleip + '/configure', json.dumps(consolesetup))
Expand Down Expand Up @@ -377,23 +380,24 @@ def pickNewTarget(consoleip):
targetval=newpin
targetinstruction = controls.getPinAction(targetname, targetval)
else:
print("Unhandled type: " + ctrltype)
log.warning("Unhandled type: %s", ctrltype)
#Now we have targetval and targetinstruction for this consoleip, store and publish it
console[consoleip]['instructions']=targetinstruction
console[consoleip]['target']={"console": targetconsole, "control": targetctrlid, "value": targetval, "timestamp": time.time(), "timeout": targettimeout}
print("Instruction: " + consoleip + '/' + targetctrlid + ' - ' + ctrltype + ' (was ' + str(curval) + ') ' + str(targetinstruction))
log.info("Instruction: ip=%s, id=%s, type=%s target=%s", consoleip, targetctrlid, ctrltype, curval, targetinstruction)
#update game stats
playerstats[consoleip]['instructions']['total'] += 1
playerstats[targetconsole]['targets']['total'] += 1
#publish!
client.publish('clients/' + consoleip + '/timeout', str(targettimeout))
client.publish('clients/' + consoleip + '/instructions', str(targetinstruction))


def showLives():
if lifeDisplay:
lives = playerstats['game']['lives']
print "Lives remaining: " + str(lives)
if 0 <= lives <= 9:
log.info("Lives remaining: %s", lives)
if 0 <= lives <= 9:
sev.displayDigit(lives)
if lives == 0:
led.solid(led.CODE_Col_White)
Expand All @@ -407,7 +411,8 @@ def showLives():
led.solid(led.CODE_Col_Yellow)
elif lives == 5:
led.solid(led.CODE_Col_Green)



def clearLives():
if lifeDisplay:
sev.clear()
Expand Down Expand Up @@ -495,22 +500,21 @@ def send_intro_text():
def initGame():
"""Kick off a new game"""
#Start game!
global gamestate
global currenttimeout
global nextID
gamestate = 'initgame'
game_state['stage'] = 'initgame'
game_state['skip_intro'] = False
clearLives()
currenttimeout = 15.0
# get game players from GameStarter
for key, value in gsIDs.iteritems():
if gs.isStartablePlayer(value):
print("Player %d (%s) startable" % (value, key))
log.info("Player %d (%s) startable", value, key)
players.append(key)
else:
print("Player %d (%s) not startable" % (value, key))
log.info("Player %d (%s) not startable", value, key)

print("Player IPs: %r, player IDs: %r" % (players, gsIDs))
log.info("Player IPs: %r, player IDs: %r", players, gsIDs)
for consoleip in players:
#Slight fudge in assuming control 5 is the big button
client.publish('clients/' + consoleip + '/5/name', "")
Expand Down Expand Up @@ -566,8 +570,7 @@ def initRound():
"""Kick off a new round"""
global numinstructions
global lastgenerated
global gamestate
gamestate = 'setupround'
game_state['stage'] = 'setupround'
playSound(random.choice(controls.soundfiles['atmosphere']))
#Dump another batch of random control names and action
defineControls()
Expand All @@ -579,11 +582,10 @@ def initRound():

def roundOver():
"""End the round and jump to Hyperspace"""
global gamestate
global currenttimeout
global lastgenerated
global warningsound
gamestate = 'roundover'
game_state['stage'] = 'roundover'
if sound and not warningsound is None:
warningsound.stop()
warningsound = None
Expand All @@ -598,15 +600,14 @@ def roundOver():
playSound(controls.soundfiles['special']['hyperspace'])
lastgenerated = time.time()
currenttimeout *= 0.75
gamestate = 'hyperspace'
game_state['stage'] = 'hyperspace'

def gameOver():
"""End the current game and dole out the medals"""
global gamestate
#Check we're not already here (fixes issue #4)
if gamestate != 'playround':
if game_state['stage'] != 'playround':
return
gamestate = 'gameover'
game_state['stage'] = 'gameover'
for consoleip in players:
client.publish('clients/' + consoleip + '/timeout', "0.0")
tellAllPlayers(players, controls.blurb['ending']['splash'])
Expand Down Expand Up @@ -656,8 +657,7 @@ def gameOver():

def resetToWaiting():
"""Reset game back to waiting for new players"""
global gamestate
gamestate = 'readytostart'
game_state['stage'] = 'readytostart'
clearLives()
for consoleip in consoles:
consolesetup = {}
Expand Down Expand Up @@ -709,17 +709,17 @@ def resetToWaiting():
if time.time() - lastReady > 3.0:
lastReady = time.time()
client.publish('server/ready', 'ready')
#if gamestate == 'waitingforplayers' and len(players) >= 1 and time.time() - lastgenerated > 5.0:
if gamestate == 'waitingforplayers' and gs.shouldStart():
#if game_state['stage'] == 'waitingforplayers' and len(players) >= 1 and time.time() - lastgenerated > 5.0:
if game_state['stage'] == 'waitingforplayers' and gs.shouldStart():
initGame()
elif gamestate == 'setupround' and time.time() - lastgenerated > 10.0:
gamestate = 'playround'
elif game_state['stage'] == 'setupround' and time.time() - lastgenerated > 10.0:
game_state['stage'] = 'playround'
for consoleip in players:
pickNewTarget(consoleip)
elif gamestate == 'playround':
elif game_state['stage'] == 'playround':
checkTimeouts()

elif gamestate == 'hyperspace' and time.time() - lastgenerated > 4.0:
elif game_state['stage'] == 'hyperspace' and time.time() - lastgenerated > 4.0:
initRound()

#If client.loop() returns non-zero, loop drops out to here.
Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
paho-mqtt
58 changes: 58 additions & 0 deletions test_client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#!/usr/bin/env python

# This is a test client emulator it just spits out some config
# and buttons for testing....

import paho.mqtt.client as paho
import logging as log

from time import sleep
import json

logger = log.getLogger()
logger.setLevel(log.DEBUG)

client = paho.Client('TestClient')
server = "127.0.0.1"


def on_connect(mosq, obj, rc):
"""Receive MQTT connection notification"""
if rc == 0:
log.info("Connected to MQTT")
else:
log.error("Failed - return code is " + rc)


def on_message():
pass


client.on_connect = on_connect
client.on_message = on_message
client.connect(server)

console_config = {
"ip": "192.168.1.1",
"controls": [
{
"id": "1",
"gamestart": "1",
"width": 16,
"supported": [
{
"type": "button"
}
]
}
]
}

client.publish('server/register', json.dumps(console_config))
console_config['ip'] = "192.168.1.2"
sleep(1)
client.publish('server/register', json.dumps(console_config))

sleep(1)
client.publish('clients/192.168.1.1/1/value', "1")
client.publish('clients/192.168.1.2/1/value', "1")