12 logging
.error('This program needs urwid')
18 logging
.error('This program needs pySerial')
21 class FuzzyAlarmClock
:
23 def __init__(self
,device
):
25 self
.serial
= serial
.Serial(device
,9600,timeout
=5)
26 except serial
.serialutil
.SerialException
:
27 logging
.warning('No such serial device {device}; mocking'.format(
30 self
.serial
= io
.StringIO()
35 def set_time_to_now(self
):
36 now
= 's'+datetime
.datetime
.now().strftime("%y%m%d%u%H%M%S")
37 self
.serial
.write(now
)
39 def read_alarms(self
,n
):
41 self
.serial
.flushInput()
42 self
.serial
.write('p')
44 data
.append(self
.serial
.readline())
46 data
[i
] = data
[i
].split(' ')[2:-1]
49 days
.append(bool(int(data
[i
][0]) & 2**j
))
50 days
= days
[7:8] + days
[:7]
51 data
[i
] = days
+data
[i
][1:]
54 def set_alarm(self
,alarm
,values
):
57 for i
,bit
in enumerate(values
[1:8] + values
[0:1]):
60 for val
in values
[8:]:
64 class ModEdit(urwid
.IntEdit
):
66 def __init__(self
,mod
,caption
="",default
=None,offset
=0):
70 super(ModEdit
,self
).__init
__(caption
,default
)
72 def insert_text(self
,text
):
73 super(ModEdit
,self
).insert_text(text
)
74 self
.set_edit_text(str((self
.value() - self
.offset
)% self
.mod
+self
.offset
))
79 def __init__(self
,aid
,fac
):
80 self
.w_aid
= urwid
.Text(str(aid
))
81 self
.w_repeat
= urwid
.CheckBox("")
82 self
.w_mon
= urwid
.CheckBox("")
83 self
.w_tue
= urwid
.CheckBox("")
84 self
.w_wed
= urwid
.CheckBox("")
85 self
.w_thu
= urwid
.CheckBox("")
86 self
.w_fri
= urwid
.CheckBox("")
87 self
.w_sat
= urwid
.CheckBox("")
88 self
.w_sun
= urwid
.CheckBox("")
89 self
.w_month
= ModEdit(12,offset
=1)
90 self
.w_day
= ModEdit(31,offset
=1)
91 self
.w_hour
= ModEdit(24,default
=0)
92 self
.w_minute
= ModEdit(60,default
=0)
94 self
.widgets
= urwid
.Columns([self
.w_aid
,
110 def set_values(self
,values
):
111 self
.w_repeat
.set_state(values
[0])
112 self
.w_mon
.set_state(values
[1])
113 self
.w_tue
.set_state(values
[2])
114 self
.w_wed
.set_state(values
[3])
115 self
.w_thu
.set_state(values
[4])
116 self
.w_fri
.set_state(values
[5])
117 self
.w_sat
.set_state(values
[6])
118 self
.w_sun
.set_state(values
[7])
119 self
.w_month
.set_edit_text(str(values
[8]))
120 self
.w_day
.set_edit_text(str(values
[9]))
121 self
.w_hour
.set_edit_text(str(values
[10]))
122 self
.w_minute
.set_edit_text(str(values
[11]))
124 def get_values(self
):
126 self
.w_repeat
.get_state(),
127 self
.w_mon
.get_state(),
128 self
.w_tue
.get_state(),
129 self
.w_wed
.get_state(),
130 self
.w_thu
.get_state(),
131 self
.w_fri
.get_state(),
132 self
.w_sat
.get_state(),
133 self
.w_sun
.get_state(),
134 self
.w_month
.value(),
137 self
.w_minute
.value(),
143 def __init__(self
,fac
):
148 self
.frame
= self
.build_ui()
149 self
.loop
= urwid
.MainLoop(self
.frame
,self
.palette
,unhandled_input
=self
.read_commands
)
153 ('header', 'light gray', 'dark blue'),
154 ('footer', 'dark cyan', 'black')
158 for i
in range(self
.alarm_number
):
159 self
.alarms
.append(Alarm(i
,self
.fac
))
161 alarm_headers
= urwid
.Columns([
176 self
.main_body
= urwid
.ListBox([alarm_headers
]+[al
.widgets
for al
in self
.alarms
])
178 footer
= urwid
.Text('a, b, c')
179 footer_map
= urwid
.AttrMap(footer
,'footer')
183 'r: Read s: Set n: time=Now ' +
184 'f: to File l: Load ' +
187 header_map
= urwid
.AttrMap(header
,'header')
189 ui
= urwid
.Frame(self
.main_body
,footer
=footer_map
,header
=header_map
)
192 def read_commands(self
,cmd
):
193 {'n': self
.fac
.set_time_to_now
,
194 'r': self
.read_alarms
,
195 's': self
.set_alarms
,
196 '?': self
.print_help
,
198 'f': self
.save_alarms
,
199 'l': self
.load_alarms
,
200 }.get(cmd
,self
.do_nothing
)()
202 def do_nothing(self
):
205 def read_alarms(self
):
206 alarms
= self
.fac
.read_alarms(self
.alarm_number
)
208 for i
, al
in enumerate(alarms
):
209 self
.alarms
[i
].set_values(al
)
211 def set_alarms(self
):
212 for i
,alarm
in enumerate(self
.alarms
):
213 self
.fac
.set_alarm(i
,alarm
.get_values())
215 def save_alarms(self
, fname
='saved_alarms.json'):
216 alarms
= [a
.get_values() for a
in self
.alarms
]
218 with
open(fname
,'w') as fp
:
219 json
.dump(alarms
, fp
)
221 def load_alarms(self
, fname
='saved_alarms.json'):
223 with
open(fname
) as fp
:
224 alarms
= json
.load(fp
)
225 except FileNotFoundError
:
226 logging
.warning('No such file: {fname}'.format(fname
=fname
))
228 # TODO: do some validation on the data
229 for i
, a
in enumerate(self
.alarms
):
231 a
.set_values(alarms
[i
])
233 def print_help(self
):
237 raise urwid
.ExitMainLoop()
244 fac
= FuzzyAlarmClock('/dev/ttyUSB0')
248 if __name__
== '__main__': main()