#!/usr/bin/env python
# encoding: utf-8
import urwid
import urwid . raw_display
import sys
import re , sys , random
from sorteddict import SortedDict
# {0x79, 0x56, 0x34, 0x12}
def rand_hw ( ) :
res = [ ]
for i in range ( 4 ) :
res . append ( random . randint ( 1 , 254 ) )
#res.insert(0, random.randint(1, 254))
res . sort ( reverse = True )
return " { " + " , " . join ( [ hex ( x ) for x in res ] ) + " } "
DATA = SortedDict ( )
DATA [ " CONFIG_FREQUENCY " ] = {
" name " : " Frequency " ,
" depends " : [ ] ,
" default " : 902 ,
" type " : " choices " ,
" values " : [ 902 , 869 , 433 ] ,
" help " : " Frequency for the clock "
}
DATA [ " OPTION_TIME_DISPLAY " ] = {
" name " : " Time display options " ,
" depends " : [ ] ,
" default " : 0 ,
" type " : " choices " ,
" values " : [ ( 0 , " 24hr " ) , ( 1 , " 12hr (AM/PM) " ) , ( 2 , " selectable " ) ] ,
" help " : " Select how time should be displayed, in order of code size options are- 0 = 24hr, 1=12hr (AM/PM) or 2=selectable "
}
DATA [ " CONFIG_METRIC_ONLY " ] = {
" name " : " Metric only code " ,
" depends " : [ ] ,
" default " : False ,
" help " : " Only add code for Metric units (meter/celsius) to reduce image size " ,
}
DATA [ " THIS_DEVICE_ADDRESS " ] = {
" name " : " Hardware address " ,
" type " : " text " ,
" default " : rand_hw ( ) ,
" ifndef " : True ,
" help " : " Default Radio Hardware Address to use on the device " ,
}
DATA [ " USE_LCD_CHARGE_PUMP " ] = {
" name " : " Use LCD Charge Pump " ,
" default " : False ,
" help " : " Use the internal charge pump to make the display contrast same tho whole battery lifetime. But this increases currency and reduces battery lifetime. " ,
}
DATA [ " USE_WATCHDOG " ] = {
" name " : " Use Watchdog " ,
" default " : True ,
" help " : " Protects the clock against deadlocks by rebooting it. " ,
}
# FIXME implement
# DATA["CONFIG_AUTOSYNC"] = {
# "name": "Automaticly SYNC after reboot",
# "default": False,
# "help": "Automaticly sync clock after reboot",
# }
DATA [ " DEBUG " ] = {
" name " : " Debug " ,
" default " : False ,
" help " : " Activates debug code " ,
}
# modules
DATA [ " CONFIG_DAY_OF_WEEK " ] = {
" name " : " Date: Day of Week " ,
" depends " : [ ] ,
" default " : True ,
" help " : " Shows day of week on the date module " ,
}
DATA [ " CONFIG_TEST " ] = {
" name " : " Test Mode " ,
" depends " : [ ] ,
" default " : True ,
" help " : " Test module to test some functionalities when the clock started " ,
}
DATA [ " TEXT_MODULES " ] = {
" name " : " Modules " ,
" type " : " info "
}
#### MODULES ####
DATA [ " CONFIG_EGGTIMER " ] = {
" name " : " Eggtimer " ,
" depends " : [ ] ,
" default " : False ,
" help " : " Countdown timer to count down from 1 minute - 20 hours to 0 and start an alarm " ,
}
DATA [ " CONFIG_PHASE_CLOCK " ] = {
" name " : " Phase Clock " ,
" depends " : [ ] ,
" default " : False ,
" help " : " Messures sleep phase by recording body movement and sends the data to the accesspoint. \n "
" Designed to be used with uberclock " ,
}
DATA [ " CONFIG_ALTITUDE " ] = {
" name " : " Altitude " ,
" depends " : [ ] ,
" default " : True ,
" help " : " Messures altitude "
}
DATA [ " CONFIG_VARIO " ] = {
" name " : " Combined with alti, gives vertical speed " ,
" depends " : [ ] ,
" default " : False }
DATA [ " CONFIG_PROUT " ] = {
" name " : " Simple example that displays a text " ,
" depends " : [ ] ,
" default " : False }
# not yet working
DATA [ " CONFIG_ACCEL " ] = {
" name " : " Accleration " ,
" depends " : [ ] ,
" default " : True }
DATA [ " CONFIG_ALARM " ] = {
" name " : " Alarm " ,
" depends " : [ ] ,
" default " : True }
DATA [ " CONFIG_BATTERY " ] = {
" name " : " Battery " ,
" depends " : [ ] ,
" default " : True }
DATA [ " CONFIG_CLOCK " ] = {
" name " : " Clock " ,
" depends " : [ ] ,
" default " : True }
DATA [ " CONFIG_DATE " ] = {
" name " : " Date " ,
" depends " : [ ] ,
" default " : True }
DATA [ " CONFIG_RFBSL " ] = {
" name " : " Wireless Update " ,
" depends " : [ ] ,
" default " : True }
DATA [ " CONFIG_STOP_WATCH " ] = {
" name " : " Stop Watch " ,
" depends " : [ ] ,
" default " : True }
DATA [ " CONFIG_TEMP " ] = {
" name " : " Temperature " ,
" depends " : [ ] ,
" default " : True }
HEADER = """
#ifndef _CONFIG_H_
#define _CONFIG_H_
"""
FOOTER = """
#endif // _CONFIG_H_
"""
# debugging functions
#FP = open("/tmp/log", "w")
#def flog(*args):
# FP.write(repr(args))
# FP.write("\n")
class HelpListWalker ( urwid . SimpleListWalker ) :
def __init__ ( self , app , * args , * * kwargs ) :
self . app = app
super ( HelpListWalker , self ) . __init__ ( * args , * * kwargs )
def set_focus ( self , focus ) :
if hasattr ( self [ focus ] , " _datafield " ) and \
" help " in self [ focus ] . _datafield :
self . app . help_widget . set_text ( self [ focus ] . _datafield [ " help " ] )
else :
self . app . help_widget . set_text ( " " )
return super ( HelpListWalker , self ) . set_focus ( focus )
class HelpGridFlow ( urwid . GridFlow ) :
def __init__ ( self , app , * args , * * kwargs ) :
self . app = app
super ( HelpGridFlow , self ) . __init__ ( * args , * * kwargs )
def set_focus ( self , focus ) :
if hasattr ( focus , " _datafield " ) and \
" help " in focus . _datafield :
self . app . help_widget . set_text ( focus . _datafield [ " help " ] )
else :
self . app . help_widget . set_text ( " " )
return super ( HelpGridFlow , self ) . set_focus ( focus )
class OpenChronosApp ( object ) :
def main ( self ) :
self . fields = { }
text_header = ( u " OpenChronos config \u2503 "
u " UP / DOWN / PAGE UP / PAGE DOWN scroll. F8 aborts. " )
self . list_content = list_content = [ ]
for key , field in DATA . iteritems ( ) :
# generate gui forms depending on type
if field . get ( " type " , " bool " ) == " bool " :
f = urwid . AttrWrap ( urwid . CheckBox ( field [ " name " ] , state = field [ " value " ] ) , ' buttn ' , ' buttnf ' )
f . _datafield = field
self . fields [ key ] = f
list_content . append ( f )
elif field [ " type " ] == " choices " :
try :
value = field [ " values " ] . index ( field [ " value " ] )
except ValueError :
value = field [ " default " ]
field [ " radio_button_group " ] = [ ]
f = urwid . Text ( field [ " name " ] )
f . _datafield = field
choice_items = [ f ]
for dat in field [ " values " ] :
txt = value = dat
if isinstance ( dat , tuple ) :
value , txt = dat
f = urwid . AttrWrap ( urwid . RadioButton ( field [ " radio_button_group " ] ,
unicode ( txt ) , state = value == field [ " value " ] ) , ' buttn ' , ' buttnf ' )
f . _datafield = field
f . value = value
choice_items . append ( f )
hgf = HelpGridFlow ( self , choice_items , 20 , 3 , 1 , ' left ' )
self . fields [ key ] = choice_items
hgf . focus_cell = hgf . cells [ 1 ]
list_content . append ( hgf )
elif field [ " type " ] == " text " :
f = urwid . AttrWrap ( urwid . Edit ( " %s : " % field [ " name " ] , field [ " value " ] ) ,
' editbx ' , ' editfc ' )
f . _datafield = field
self . fields [ key ] = f
list_content . append ( f )
elif field [ " type " ] == " info " :
f = urwid . Text ( field [ " name " ] )
f . _datafield = field
self . fields [ key ] = f
list_content . append ( f )
def ok_pressed ( * args , * * kwargs ) :
raise urwid . ExitMainLoop ( )
def abort_pressed ( * args , * * kwargs ) :
sys . exit ( 0 )
list_content . append ( urwid . Divider ( div_char = u " \u2550 " , top = 1 , bottom = 1 ) )
list_content . append (
urwid . Padding ( urwid . GridFlow (
[ urwid . AttrWrap ( urwid . Button ( " Save " , ok_pressed ) , ' buttn ' , ' buttnf ' ) ,
urwid . AttrWrap ( urwid . Button ( " Abort " , abort_pressed ) , ' buttn ' , ' buttnf ' ) ] ,
15 , 4 , 4 , ' center ' ) ,
( ' fixed left ' , 4 ) , ( ' fixed right ' , 3 ) ) )
header = urwid . AttrWrap ( urwid . Text ( text_header ) , ' header ' )
#header = urwid.Padding(urwid.BigText("OpenChronos", urwid.HalfBlock5x4Font()))
walker = HelpListWalker ( self , list_content )
listbox = urwid . ListBox ( walker )
self . help_widget = urwid . Text ( " " )
footer = urwid . AttrWrap ( self . help_widget , ' footer ' )
frame = urwid . Frame ( urwid . AttrWrap ( listbox , ' body ' ) , header = header , footer = footer )
screen = urwid . raw_display . Screen ( )
palette = [
( ' body ' , ' black ' , ' light gray ' , ' standout ' ) ,
( ' reverse ' , ' light gray ' , ' black ' ) ,
( ' header ' , ' white ' , ' dark red ' , ' bold ' ) ,
( ' important ' , ' dark blue ' , ' light gray ' , ( ' standout ' , ' underline ' ) ) ,
( ' editfc ' , ' white ' , ' dark blue ' , ' bold ' ) ,
( ' editbx ' , ' light gray ' , ' dark blue ' ) ,
( ' editcp ' , ' black ' , ' light gray ' , ' standout ' ) ,
( ' bright ' , ' dark gray ' , ' light gray ' , ( ' bold ' , ' standout ' ) ) ,
( ' buttn ' , ' black ' , ' dark cyan ' ) ,
( ' buttnf ' , ' white ' , ' dark blue ' , ' bold ' ) ,
]
def unhandled ( key ) :
if key == ' f8 ' :
#raise urwid.ExitMainLoop()
sys . exit ( 0 )
urwid . MainLoop ( frame , palette , screen ,
unhandled_input = unhandled ) . run ( )
def save_config ( self ) :
for key , field in self . fields . iteritems ( ) :
if isinstance ( field , ( tuple , list ) ) :
for item in field :
if hasattr ( item , " get_state " ) :
if item . get_state ( ) :
# found the set radio button
DATA [ key ] [ " value " ] = item . value
# look up the
elif isinstance ( field , urwid . Text ) :
pass
elif isinstance ( field , urwid . AttrMap ) :
wid = field . original_widget
if isinstance ( wid , urwid . Edit ) :
DATA [ key ] [ " value " ] = wid . get_edit_text ( )
else :
DATA [ key ] [ " value " ] = wid . get_state ( )
else :
raise ValueError , " Unhandled type "
fp = open ( " config.h " , " w " )
fp . write ( " // !!!! DO NOT EDIT !!!, use: make config \n " )
fp . write ( HEADER )
for key , dat in DATA . iteritems ( ) :
if not " value " in dat :
continue
if " type " in dat and dat [ " type " ] == " info " :
continue
if DATA [ key ] . get ( " ifndef " , False ) :
fp . write ( " #ifndef %s \n " % key )
if isinstance ( dat [ " value " ] , bool ) :
if dat [ " value " ] :
fp . write ( " #define %s \n " % key )
else :
fp . write ( " // %s is not set \n " % key )
else :
fp . write ( " #define %s %s \n " % ( key , dat [ " value " ] ) )
if DATA [ key ] . get ( " ifndef " , False ) :
fp . write ( " #endif // %s \n " % key )
fp . write ( FOOTER )
def load_config ( self ) :
def set_default ( ) :
for key , dat in DATA . iteritems ( ) :
#print dat
if not " value " in dat and " default " in dat :
dat [ " value " ] = dat [ " default " ]
try :
fp = open ( " config.h " )
except ( OSError , IOError ) :
set_default ( )
return
match = re . compile ( ' ^[ \t ]*#[ \t ]*define[ \t ]+([a-zA-Z0-9_]+)[ \t ]*(.*)$ ' )
match2 = re . compile ( ' ^// ([a-zA-Z0-9_]+) is not set$ ' )
for line in fp :
m = match . search ( line )
if m :
m = m . groups ( )
if not m [ 0 ] in DATA :
continue
if m [ 1 ] == " " :
DATA [ m [ 0 ] ] [ " value " ] = True
else :
try :
value = int ( m [ 1 ] )
except ValueError :
value = m [ 1 ]
DATA [ m [ 0 ] ] [ " value " ] = value
else :
m = match2 . search ( line )
if m and m . groups ( ) [ 0 ] in DATA :
m = m . groups ( )
DATA [ m [ 0 ] ] [ " value " ] = False
set_default ( )
if __name__ == " __main__ " :
App = OpenChronosApp ( )
App . load_config ( )
App . main ( )
App . save_config ( )