├── .gitignore
├── .project
├── .pydevproject
├── .settings
└── org.eclipse.core.resources.prefs
├── Button
├── Makefile
├── generate_uinput_names.sh
├── gpio-keys
├── gpio-keys.c
└── uinput_names.inc
├── Clock
├── .gitignore
├── ApiKeys-example.py
├── Config-Example-Bedside.py
├── Config-Example-Berlin.py
├── Config-Example-London.py
├── Config-Example.py
├── GoogleMercatorProjection.py
├── PyQtPiClock.py
├── icons-darkblue
│ ├── .gitignore
│ ├── clear-day.png
│ ├── clear-night.png
│ ├── cloudy.png
│ ├── fog.png
│ ├── partly-cloudy-day.png
│ ├── partly-cloudy-night.png
│ ├── rain.png
│ ├── sleet.png
│ ├── snow.png
│ ├── thunderstorm.png
│ └── wind.png
├── icons-darkgreen
│ ├── clear-day.png
│ ├── clear-night.png
│ ├── cloudy.png
│ ├── fog.png
│ ├── partly-cloudy-day.png
│ ├── partly-cloudy-night.png
│ ├── rain.png
│ ├── sleet.png
│ ├── snow.png
│ ├── thunderstorm.png
│ └── wind.png
├── icons-lightblue
│ ├── .gitignore
│ ├── clear-day.png
│ ├── clear-night.png
│ ├── cloudy.png
│ ├── fog.png
│ ├── partly-cloudy-day.png
│ ├── partly-cloudy-night.png
│ ├── rain.png
│ ├── sleet.png
│ ├── snow.png
│ ├── thunderstorm.png
│ └── wind.png
├── images
│ ├── .gitignore
│ ├── berlin-at-night-mrwallpaper.jpg
│ ├── clockbackground-chris.png
│ ├── clockbackground-jean.png
│ ├── clockbackground-kelly.png
│ ├── clockbackground-kevin.png
│ ├── clockbackground.png
│ ├── clockface3-darkblue.png
│ ├── clockface3-darkgreen.png
│ ├── clockface3.png
│ ├── hourhand-darkblue.png
│ ├── hourhand-darkgreen.png
│ ├── hourhand.png
│ ├── minhand-darkblue.png
│ ├── minhand-darkgreen.png
│ ├── minhand.png
│ ├── sechand-darkblue.png
│ ├── sechand-darkgreen.png
│ ├── sechand.png
│ ├── slideshow
│ │ ├── daniel-h-tong-1310255-unsplash.jpg
│ │ ├── johannes-plenio-629984-unsplash.jpg
│ │ ├── nasa-53888-unsplash.jpg
│ │ ├── patrick-tomasso-1311143-unsplash.jpg
│ │ ├── roman-bozhko-251398-unsplash.jpg
│ │ └── shot-by-cerqueira-1318576-unsplash.jpg
│ ├── squares1-green.png
│ ├── squares1-jean.png
│ ├── squares1-kevin.png
│ ├── squares2-green.png
│ ├── squares2-jean.png
│ └── squares2-kevin.png
└── markers
│ ├── Readme.md
│ ├── markers.xcf
│ ├── teardrop-dot.png
│ ├── teardrop-family.png
│ ├── teardrop-home.png
│ ├── teardrop-school.png
│ ├── teardrop-work.png
│ └── teardrop.png
├── Contributed
├── PiClock_neo-aeon-Clockface-FliegerB.zip
├── PiClock_neo-aeon-ClockfaceGuide-GIMP.zip
└── Readme.md
├── Documentation
├── 2015-06-11_10-36-44.png
├── Digital Clock v1.jpg
├── Digital Clock v2.jpg
├── Hardware.md
├── Hardware_Schematic.pdf
├── Hardware_Schematic.png
├── Hardware_Schematic.sch
├── Install-Clock-Only.md
├── Install-Jessie.md
├── Install.md
├── NeoPixel.jpg
├── Overview.md
├── ds18b20.jpg
├── gpiobuttons.jpg
└── tsop4838.jpg
├── IR
├── IRCodes.pl
└── lircd.conf
├── LICENSE
├── Leds
└── NeoAmbi.py
├── PiClock.desktop
├── Pictures
├── 20141222_220127.jpg
├── 20141227_174953.jpg
├── 2015-05-10_17-01-52.png
├── 2015-05-16_17-36-06.png
├── 20150307_222711.jpg
├── 20150326_225245.jpg
├── 20150326_225305_Fotor_Collage.jpg
├── 20150404_165441_Fotor_Collage.jpg
└── 20150412_182821a.jpg
├── README.md
├── Temperature
├── TempNames.py
└── TempServer.py
├── gimp
├── Readme.md
├── clockbackground.xcf
├── clockbackground5.xcf
├── clockface3.xcf
├── hourhand.xcf
├── jeansxcf.xcf
├── minhand.xcf
├── sechand.xcf
├── squares2.xcf
└── squres1.xcf
├── startup.sh
├── switcher.sh
└── update.py
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 |
5 | # Configuration things to not commit API keys/location
6 | Clock/Api-Keys.py
7 | Clock/Config.py
8 |
9 | # From testing
10 | Clock/log.count
11 | Clock/*.log*
12 |
13 | # Distribution / packaging
14 | .Python
15 | env/
16 | build/
17 | develop-eggs/
18 | dist/
19 | downloads/
20 | eggs/
21 | .eggs/
22 | lib/
23 | lib64/
24 | parts/
25 | sdist/
26 | var/
27 | *.egg-info/
28 | .installed.cfg
29 | *.egg
30 |
31 | # PyInstaller
32 | # Usually these files are written by a python script from a template
33 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
34 | *.manifest
35 | *.spec
36 |
37 | # Installer logs
38 | pip-log.txt
39 | pip-delete-this-directory.txt
40 |
41 | # Unit test / coverage reports
42 | htmlcov/
43 | .tox/
44 | .coverage
45 | .coverage.*
46 | .cache
47 | nosetests.xml
48 | coverage.xml
49 | *,cover
50 |
51 | # Translations
52 | *.mo
53 | *.pot
54 |
55 | # Django stuff:
56 | *.log
57 |
58 | # Sphinx documentation
59 | docs/_build/
60 |
61 | # PyBuilder
62 | target/
63 |
64 | Thumbs.db
65 |
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | PiClock
4 |
5 |
6 |
7 |
8 |
9 | org.python.pydev.PyDevBuilder
10 |
11 |
12 |
13 |
14 |
15 | org.python.pydev.pythonNature
16 |
17 |
18 |
--------------------------------------------------------------------------------
/.pydevproject:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | /${PROJECT_DIR_NAME}
5 | /${PROJECT_DIR_NAME}/Clock
6 |
7 | python 2.7
8 | Default
9 |
10 |
--------------------------------------------------------------------------------
/.settings/org.eclipse.core.resources.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | encoding//Clock/Config-Example-Berlin.py=utf-8
3 | encoding//Clock/PyQtPiClock.py=utf-8
4 |
--------------------------------------------------------------------------------
/Button/Makefile:
--------------------------------------------------------------------------------
1 | CFLAGS= -Wall -Werror -Wextra
2 |
3 | all: gpio-keys
4 |
5 | gpio-keys.o: gpio-keys.c uinput_names.inc
6 |
7 | uinput_names.inc:
8 | sh generate_uinput_names.sh >uinput_names.inc
9 |
10 | clean:
11 | rm gpio-keys gpio-keys.o uinput_names.inc
12 |
--------------------------------------------------------------------------------
/Button/generate_uinput_names.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # taken from input_map.sh from lircd distribution
3 | # http://www.lirc.org/
4 |
5 | TYPES="KEY BTN"
6 | file=${1:-/usr/include/linux/input.h}
7 |
8 | # Use gnu-sed on Macosx
9 | if test "`uname`" = 'Darwin'; then
10 | SED=gsed
11 | else
12 | SED=sed
13 | fi
14 |
15 | for type in $TYPES; do
16 | grep "^#define ${type}_" < $file|sort|$SED -n --expression="s/^#define \([^ \t]*\)[ \t][ \t]*\([0-9][0-9a-fA-FxX]*\).*/{\"\1\", \2},/p"
17 | done
18 |
--------------------------------------------------------------------------------
/Button/gpio-keys:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Button/gpio-keys
--------------------------------------------------------------------------------
/Button/gpio-keys.c:
--------------------------------------------------------------------------------
1 | /*
2 | The MIT License (MIT)
3 |
4 | Copyright (c) 2015 Kevin Uhlir
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in
14 | all copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | THE SOFTWARE.
23 |
24 |
25 | Portions taken from input_map.sh from lircd distribution http://www.lirc.org/
26 | Copyright (C) 2008 Christoph Bartelmus (MIT License)
27 |
28 | Portions taken from RPi-GPIO https://pypi.python.org/pypi/RPi.GPIO
29 | Copyright (c) 2012-2015 Ben Croston (MIT License)
30 |
31 |
32 |
33 | */
34 |
35 |
36 | #include
37 | #include
38 | #include
39 | #include
40 | #include
41 | #include
42 | #include
43 | #include
44 | #include
45 | #include
46 | #include
47 | #include
48 | #include
49 |
50 | int debug = 0;
51 |
52 | typedef struct {
53 | int pin;
54 | int key;
55 | int last;
56 | int fd;
57 | } pin_t;
58 |
59 | struct uinput_key {
60 | char *name;
61 | unsigned short code;
62 |
63 | } uinput_keys[] = {
64 | #include "uinput_names.inc"
65 | {
66 | NULL, 0}
67 | };
68 |
69 | #define MAX_KEYS 50
70 | static pin_t keys[MAX_KEYS];
71 | struct pollfd pollfds[MAX_KEYS];
72 | int pollfd_count = 0;
73 |
74 | int ufd = -1;
75 | static char *config_file = NULL;
76 | static char *device_name = NULL;
77 |
78 |
79 | int keycode(char *name)
80 | {
81 | if (isdigit(name[0]))
82 | {
83 | int code = strtol(name,NULL,0);
84 | if (code == 0) return(-1);
85 | return(code);
86 | }
87 | struct uinput_key *i;
88 | for (i = uinput_keys; i->name; i++)
89 | {
90 | if (strcmp(name,i->name) == 0)
91 | {
92 | return(i->code);
93 | }
94 | }
95 | return(-1);
96 | }
97 |
98 | static char keynametmp[50];
99 | char * keyname(int code)
100 | {
101 | struct uinput_key *i;
102 | for (i = uinput_keys; i->name; i++)
103 | {
104 | if (i->code == code)
105 | {
106 | return(i->name);
107 | }
108 | }
109 | sprintf(keynametmp,"unknown(0x%x)",code);
110 | return(keynametmp);
111 | }
112 |
113 | static int read_value (int fd)
114 | {
115 | char v;
116 |
117 | if (lseek (fd, 0, SEEK_SET) < 0) {
118 | perror ("lseek");
119 | exit (0);
120 | }
121 | if (read (fd, &v, 1) != 1) {
122 | perror ("read");
123 | exit (0);
124 | }
125 | return v == '0' ? 0 : 1;
126 | }
127 |
128 |
129 | #define BCM2708_PERI_BASE_DEFAULT 0x20000000
130 | #define GPIO_BASE_OFFSET 0x200000
131 | #define FSEL_OFFSET 0 // 0x0000
132 | #define SET_OFFSET 7 // 0x001c / 4
133 | #define CLR_OFFSET 10 // 0x0028 / 4
134 | #define PINLEVEL_OFFSET 13 // 0x0034 / 4
135 | #define EVENT_DETECT_OFFSET 16 // 0x0040 / 4
136 | #define RISING_ED_OFFSET 19 // 0x004c / 4
137 | #define FALLING_ED_OFFSET 22 // 0x0058 / 4
138 | #define HIGH_DETECT_OFFSET 25 // 0x0064 / 4
139 | #define LOW_DETECT_OFFSET 28 // 0x0070 / 4
140 | #define PULLUPDN_OFFSET 37 // 0x0094 / 4
141 | #define PULLUPDNCLK_OFFSET 38 // 0x0098 / 4
142 |
143 | #define PAGE_SIZE (4*1024)
144 | #define BLOCK_SIZE (4*1024)
145 |
146 |
147 | #define PUD_OFF 0
148 | #define PUD_DOWN 1
149 | #define PUD_UP 2
150 |
151 |
152 | static volatile uint32_t *gpio_map;
153 |
154 | void short_wait(void)
155 | {
156 | int i;
157 |
158 | for (i=0; i<150; i++) { // wait 150 cycles
159 | asm volatile("nop");
160 | }
161 | }
162 |
163 | void gpio_setup(void)
164 | {
165 | int mem_fd;
166 | uint8_t *gpio_mem;
167 | uint32_t peri_base = BCM2708_PERI_BASE_DEFAULT;
168 | uint32_t gpio_base;
169 | unsigned char buf[4];
170 | FILE *fp;
171 |
172 | // get peri base from device tree
173 | if ((fp = fopen("/proc/device-tree/soc/ranges", "rb")) != NULL) {
174 | fseek(fp, 4, SEEK_SET);
175 | if (fread(buf, 1, sizeof buf, fp) == sizeof buf) {
176 | peri_base = buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3] << 0;
177 | }
178 | fclose(fp);
179 | }
180 |
181 | gpio_base = peri_base + GPIO_BASE_OFFSET;
182 |
183 | // mmap the GPIO memory registers
184 | if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0) {
185 | perror ("/dev/mem");
186 | exit (1);
187 | }
188 |
189 | if ((gpio_mem = malloc(BLOCK_SIZE + (PAGE_SIZE-1))) == NULL) {
190 | perror ("gpio malloc");
191 | exit (1);
192 | }
193 |
194 | if ((uint32_t)gpio_mem % PAGE_SIZE)
195 | gpio_mem += PAGE_SIZE - ((uint32_t)gpio_mem % PAGE_SIZE);
196 |
197 | gpio_map = (uint32_t *)mmap( (caddr_t)gpio_mem, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FIXED, mem_fd, gpio_base);
198 |
199 | if ((void *)gpio_map == MAP_FAILED) {
200 | perror ("gpio memmap");
201 | exit (1);
202 | }
203 |
204 | }
205 |
206 | void set_pullupdn(int gpio, int pud)
207 | {
208 | int clk_offset = PULLUPDNCLK_OFFSET + (gpio/32);
209 | int shift = (gpio%32);
210 |
211 | if (pud == PUD_DOWN)
212 | *(gpio_map+PULLUPDN_OFFSET) = (*(gpio_map+PULLUPDN_OFFSET) & ~3) | PUD_DOWN;
213 | else if (pud == PUD_UP)
214 | *(gpio_map+PULLUPDN_OFFSET) = (*(gpio_map+PULLUPDN_OFFSET) & ~3) | PUD_UP;
215 | else // pud == PUD_OFF
216 | *(gpio_map+PULLUPDN_OFFSET) &= ~3;
217 |
218 | short_wait();
219 | *(gpio_map+clk_offset) = 1 << shift;
220 | short_wait();
221 | *(gpio_map+PULLUPDN_OFFSET) &= ~3;
222 | *(gpio_map+clk_offset) = 0;
223 | }
224 |
225 | void gpio_cleanup(void)
226 | {
227 | munmap((caddr_t)gpio_map, BLOCK_SIZE);
228 | }
229 |
230 | void uinput_setup()
231 | {
232 | pin_t *k;
233 | ufd = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
234 | if (ufd < 0) {
235 | perror ("open error: /dev/uinput");
236 | exit (1);
237 | }
238 |
239 | if (ioctl (ufd, UI_SET_EVBIT, EV_KEY) < 0
240 | || ioctl (ufd, UI_SET_EVBIT, EV_REL) < 0) {
241 | perror ("ioctl UI_SET_EVBIT");
242 | exit (1);
243 | }
244 | if (debug > 1) fprintf(stderr,"opened uinput\n");
245 |
246 | struct uinput_user_dev uinp;
247 | snprintf (uinp.name, sizeof (uinp.name), device_name ? device_name : "gpio button device");
248 | uinp.id.version = 4; /* lies, lies, lies */
249 | uinp.id.bustype = BUS_USB;
250 | uinp.id.product = 1;
251 | uinp.id.vendor = 1;
252 |
253 | if (write (ufd, &uinp, sizeof (uinp)) != sizeof (uinp)) {
254 | perror ("write error initializing: /dev/uinput");
255 | exit (1);
256 | }
257 |
258 | if (debug > 0) fprintf(stderr,"setup uinput device %s\n",uinp.name);
259 |
260 | for (k = keys; k->key; k++)
261 | {
262 | if (ioctl (ufd, UI_SET_KEYBIT, k->key) < 0) {
263 | perror ("ioctl UI_SET_KEYBIT");
264 | exit (1);
265 | }
266 |
267 | if (debug > 0) fprintf(stderr,"uinput keycode set 0x%x %s for gpio pin %d\n",
268 | k->key,keyname(k->key),k->pin);
269 |
270 | }
271 | if (ioctl(ufd, UI_DEV_CREATE) < 0) {
272 | perror ("ioctl UI_DEV_CREATE");
273 | exit (1);
274 | }
275 |
276 | if (debug > 0) fprintf(stderr,"uinput device created\n");
277 | }
278 |
279 |
280 | void pollfd_setup()
281 | {
282 | pin_t *k;
283 | pollfd_count = 0;
284 | for (k = keys; k->key; k++)
285 | {
286 | pollfd_count++;
287 | }
288 |
289 | struct pollfd *p = pollfds;
290 | for (k = keys; k->key; k++, p++)
291 | {
292 | p->fd = k->fd;
293 | p->events = POLLPRI;
294 | p->revents = 0;
295 | }
296 |
297 |
298 |
299 | }
300 |
301 | void gpio_sys_setup()
302 | {
303 | char path[300];
304 | char epath[300];
305 | char num[20];
306 | FILE *efp;
307 | FILE *fp;
308 | pin_t *k;
309 | snprintf (epath, sizeof (epath), "/sys/class/gpio/export");
310 | efp = fopen (epath, "w");
311 | if (!efp) {
312 | fprintf(stderr,"open error:");
313 | perror (epath);
314 | exit (1);
315 | }
316 | for (k = keys; k->key; k++)
317 | {
318 |
319 | // see if the pin is exported
320 | snprintf (path, sizeof (path), "/sys/class/gpio/gpio%d/value", k->pin);
321 | int fd = open (path, O_RDONLY);
322 | if (fd < 0) // not exported
323 | {
324 |
325 | // export the pin
326 | snprintf (num, sizeof (num), "%d", k->pin);
327 | if (fputs (num, efp) < 0) {
328 | fprintf(stderr,"write error:");
329 | perror (epath);
330 | exit (1);
331 | }
332 | if (fflush (efp) < 0) {
333 | fprintf(stderr,"flush error:");
334 | perror (epath);
335 | exit (1);
336 | }
337 | if (debug > 1) fprintf(stderr,"exported gpio %d\n",k->pin);
338 | }
339 | else
340 | {
341 | if (debug > 1) fprintf(stderr,"gpio %d already exported\n",k->pin);
342 | close(fd);
343 | }
344 | }
345 |
346 | usleep(100000);
347 |
348 | for (k = keys; k->key; k++)
349 | {
350 |
351 | set_pullupdn(k->pin, PUD_UP);
352 |
353 | if (debug > 1) fprintf(stderr,"gpio %d pullup set\n",k->pin);
354 |
355 | // set direction input
356 | snprintf (path, sizeof (path), "/sys/class/gpio/gpio%d/direction", k->pin);
357 | fp = fopen (path, "w");
358 | if (!fp) {
359 | fprintf(stderr,"open error:");
360 | perror (path);
361 | exit (1);
362 | }
363 | if (fputs ("in", fp) < 0) {
364 | fprintf(stderr,"write error:");
365 | perror (path);
366 | exit (1);
367 | }
368 | if (fclose (fp) != 0) {
369 | fprintf(stderr,"close error:");
370 | perror (path);
371 | exit (1);
372 | }
373 |
374 |
375 | // set edge interrupt
376 | snprintf (path, sizeof (path), "/sys/class/gpio/gpio%d/edge", k->pin);
377 | fp = fopen (path, "w");
378 | if (!fp) {
379 | fprintf(stderr,"open error:");
380 | perror (path);
381 | exit (1);
382 | }
383 | if (fputs ("both", fp) < 0) {
384 | fprintf(stderr,"write error:");
385 | perror (path);
386 | exit (1);
387 | }
388 | if (fclose (fp) != 0) {
389 | fprintf(stderr,"close error:");
390 | perror (path);
391 | exit (1);
392 | }
393 |
394 | if (debug > 1) fprintf(stderr,"gpio %d edge interupt set\n",k->pin);
395 | // open value file
396 |
397 |
398 | snprintf (path, sizeof (path), "/sys/class/gpio/gpio%d/value", k->pin);
399 | int fd = open (path, O_RDONLY);
400 | if (fd < 0) {
401 | fprintf(stderr,"open error:");
402 | perror (path);
403 | exit (1);
404 | }
405 |
406 |
407 | k->fd = fd;
408 | k->last = read_value (k->fd);
409 |
410 | }
411 |
412 | fclose (efp);
413 | }
414 |
415 | static void init(void)
416 | {
417 |
418 | gpio_setup();
419 |
420 | gpio_sys_setup();
421 |
422 | uinput_setup();
423 |
424 | pollfd_setup();
425 |
426 | }
427 |
428 |
429 |
430 | static void sendkey(int code, int val)
431 | {
432 | struct input_event ev;
433 |
434 | memset (&ev, 0, sizeof (ev));
435 | ev.type = EV_KEY;
436 | ev.code = code;
437 | ev.value = val;
438 |
439 | if (write (ufd, &ev, sizeof (ev)) != sizeof (ev)) {
440 | perror ("write key_event");
441 | exit (1);
442 | }
443 |
444 | ev.type = EV_SYN;
445 | ev.code = SYN_REPORT;
446 | ev.value = 0;
447 |
448 | if (write (ufd, &ev, sizeof (ev)) != sizeof (ev)) {
449 | perror ("write syn_event");
450 | exit (1);
451 | }
452 |
453 | if (debug > 0) fprintf(stderr,"key sent 0x%x %s %s\n",code,keyname(code),val?"pressed":"released");
454 |
455 | }
456 |
457 | static void one_event(void )
458 | {
459 |
460 | if (poll (pollfds, pollfd_count, -1) < 0) {
461 | perror ("poll");
462 | exit (1);
463 | }
464 |
465 |
466 | struct pollfd *p;
467 | pin_t *k;
468 | int pc;
469 | for (k = keys, p = pollfds, pc = pollfd_count; pc > 0; p++, k++, pc--)
470 | {
471 | if (p->revents & POLLPRI)
472 | {
473 | usleep(20000); // 20ms debounce
474 | int v = read_value(k->fd);
475 | if (k->last != v)
476 | {
477 | if (debug > 0) fprintf(stderr,"gpio button change %d value %d\n",k->pin,v);
478 | sendkey(k->key,v ^ 1);
479 | }
480 | k->last = v;
481 | }
482 | p->revents = 0;
483 | p->events = POLLPRI;
484 | }
485 |
486 | }
487 |
488 |
489 | void sighandler(int s)
490 | {
491 | (void)s;
492 | if (debug > 0) fprintf(stderr,"shutting down\n");
493 | if (ufd > -1) ioctl (ufd, UI_DEV_DESTROY );
494 | if (debug > 0) fprintf(stderr,"uinput device destroyed\n");
495 | char epath[300];
496 | snprintf (epath, sizeof (epath), "/sys/class/gpio/unexport");
497 | FILE *efp = fopen (epath, "w");
498 | if (!efp) {
499 | fprintf(stderr,"open error:");
500 | perror (epath);
501 | exit (1);
502 | }
503 | pin_t *k;
504 | for (k = keys; k->key; k++)
505 | {
506 | close(k->fd);
507 | char num[10];
508 | snprintf (num, sizeof (num), "%d", k->pin);
509 | if (fputs (num, efp) < 0) {
510 | fprintf(stderr,"write error:");
511 | perror (epath);
512 | exit (1);
513 | }
514 | if (fflush (efp) < 0) {
515 | fprintf(stderr,"flush error:");
516 | perror (epath);
517 | exit (1);
518 | }
519 | if (debug > 0) fprintf(stderr,"unexported %d\n",k->pin);
520 | set_pullupdn(k->pin, PUD_OFF);
521 | if (debug > 1) fprintf(stderr,"pullup turned off %d\n",k->pin);
522 | }
523 | fclose(efp);
524 | if (debug > 0) fprintf(stderr,"shutdown complete\n");
525 | exit(0);
526 | }
527 |
528 | void usage(void)
529 | {
530 | fprintf(stderr,"\ngpio-keys: [options] gpio:keyname, ...\n"
531 | " -h --help this message\n"
532 | " -c --config-file specify a config file\n"
533 | " -n --device-name specify the device name for creating the uinput device\n"
534 | " gpio:keyname for specifying the gpio pin which will be mapped to a keyname\n"
535 | "\n"
536 | " Multiple gpio:keyname can be specified\n"
537 | "\n"
538 | " A config file consists of lines with gpio and keyname pairs, one per line\n"
539 | " lines starting with # are taken as comment lines\n"
540 | "\n"
541 | " gpio-keys requires root privileges (because it uses uinput)\n"
542 | );
543 |
544 | }
545 |
546 | int main(int argc, char **argv)
547 | {
548 |
549 | int c;
550 | pin_t *kp = keys;
551 | pin_t *kp2;
552 | char *colon;
553 |
554 | memset(keys,0,sizeof(keys));
555 | while (1) {
556 | int option_index = 0;
557 | static struct option long_options[] = {
558 | {"config-file", required_argument, 0, 'c' },
559 | {"device-name", required_argument, 0, 'n' },
560 | {"help", no_argument, 0, 'h' },
561 | {"debug", no_argument, 0, 'd' },
562 | {0, 0, 0, 0 }
563 | };
564 |
565 | c = getopt_long(argc, argv, "c:n:k:dh",
566 | long_options, &option_index);
567 | if (c == -1)
568 | break;
569 |
570 | switch (c) {
571 | case 'c':
572 | config_file = strdup(optarg);
573 | break;
574 | case 'n':
575 | device_name = strdup(optarg);
576 | break;
577 | case 'h':
578 | usage();
579 | exit(0);
580 | break;
581 | case 'd':
582 | debug++;
583 | break;
584 |
585 | case '?':
586 | default:
587 | fprintf(stderr,"Unknown option: %c\n",c);
588 | usage();
589 | exit(1);
590 | }
591 | }
592 |
593 | if (optind < argc) {
594 | while (optind < argc) {
595 | optarg = argv[optind++];
596 | colon = strchr(optarg,':');
597 | if (!colon)
598 | {
599 | fprintf(stderr,"Unknown key syntax: %s\n",optarg);
600 | usage();
601 | exit(1);
602 | }
603 | colon++;
604 | int pin = atoi(optarg);
605 | int key = keycode(colon);
606 | if (key < 0)
607 | {
608 | fprintf(stderr,"Unknown key code: %s\n",colon);
609 | usage();
610 | exit(1);
611 | }
612 | for (kp2 = keys; kp2->key; kp2++)
613 | {
614 | if (kp2->pin == pin)
615 | {
616 | fprintf(stderr,"gpio pin %d already set as keycode 0x%x %s for command line argument: %s\n",
617 | pin, kp2->key, keyname(kp2->key), optarg);
618 | usage();
619 | exit(1);
620 | }
621 | }
622 | if (debug > 0) fprintf(stderr,"adding gpio pin %d as keycode 0x%x %s\n",
623 | pin,key, keyname(key));
624 | kp->pin = pin;
625 | kp->key = key;
626 | kp++;
627 | if ((kp - keys) >= MAX_KEYS)
628 | {
629 | fprintf(stderr, " too many keys specfied. %d max.\n",MAX_KEYS);
630 | usage();
631 | exit(1);
632 | }
633 | }
634 | }
635 |
636 | if (config_file)
637 | {
638 | FILE *fp;
639 | if ((fp = fopen(config_file, "r")) != NULL) {
640 | int pin;
641 | char name[51];
642 | char line[255];
643 | while(fgets(line,250,fp) != NULL)
644 | {
645 | if (line[0] == '#') continue;
646 | if (sscanf(line,"%d%50s",&pin,name) == 2)
647 | {
648 | int key = keycode(name);
649 | if (key < 0)
650 | {
651 | fprintf(stderr,"Unknown key code while reading %s: %s\n",config_file,name);
652 | usage();
653 | exit(1);
654 | }
655 | for (kp2 = keys; kp2->key; kp2++)
656 | {
657 | if (kp2->pin == pin)
658 | {
659 | fprintf(stderr,"gpio pin %d already set as keycode 0x%x %s for config line: %s\n",
660 | pin, kp2->key, keyname(kp2->key),line);
661 | usage();
662 | exit(1);
663 | }
664 | }
665 | if (debug > 0) fprintf(stderr,"adding gpio pin %d as keycode 0x%x %s\n",
666 | pin,key, keyname(key));
667 | kp->pin = pin;
668 | kp->key = key;
669 | kp++;
670 | if ((kp - keys) >= MAX_KEYS)
671 | {
672 | fprintf(stderr, " too many keys specfied. %d max.\n",MAX_KEYS);
673 | usage();
674 | exit(1);
675 | }
676 | }
677 | }
678 | fclose(fp);
679 | }
680 | else
681 | {
682 | fprintf(stderr,"can't open config file: %s\n",config_file);
683 | usage();
684 | exit(1);
685 | }
686 | }
687 |
688 | if (keys[0].key == 0)
689 | {
690 | fprintf(stderr,"No gpio keys specified... nothing to do... quitting.\n");
691 | usage();
692 | exit(1);
693 | }
694 | init();
695 | signal(SIGINT, sighandler);
696 | signal(SIGTERM, sighandler);
697 |
698 | for(;;)
699 | {
700 | one_event();
701 | }
702 |
703 | return(0);
704 | }
705 |
706 |
--------------------------------------------------------------------------------
/Button/uinput_names.inc:
--------------------------------------------------------------------------------
1 | {"KEY_0", 11},
2 | {"KEY_1", 2},
3 | {"KEY_102ND", 86},
4 | {"KEY_10CHANNELSDOWN", 0x1b9},
5 | {"KEY_10CHANNELSUP", 0x1b8},
6 | {"KEY_2", 3},
7 | {"KEY_3", 4},
8 | {"KEY_4", 5},
9 | {"KEY_5", 6},
10 | {"KEY_6", 7},
11 | {"KEY_7", 8},
12 | {"KEY_8", 9},
13 | {"KEY_9", 10},
14 | {"KEY_A", 30},
15 | {"KEY_AB", 0x196},
16 | {"KEY_ADDRESSBOOK", 0x1ad},
17 | {"KEY_AGAIN", 129},
18 | {"KEY_ALTERASE", 222},
19 | {"KEY_ANGLE", 0x173},
20 | {"KEY_APOSTROPHE", 40},
21 | {"KEY_ARCHIVE", 0x169},
22 | {"KEY_AUDIO", 0x188},
23 | {"KEY_AUX", 0x186},
24 | {"KEY_B", 48},
25 | {"KEY_BACK", 158},
26 | {"KEY_BACKSLASH", 43},
27 | {"KEY_BACKSPACE", 14},
28 | {"KEY_BASSBOOST", 209},
29 | {"KEY_BATTERY", 236},
30 | {"KEY_BLUE", 0x191},
31 | {"KEY_BLUETOOTH", 237},
32 | {"KEY_BOOKMARKS", 156},
33 | {"KEY_BREAK", 0x19b},
34 | {"KEY_BRIGHTNESSDOWN", 224},
35 | {"KEY_BRIGHTNESSUP", 225},
36 | {"KEY_BRIGHTNESS_CYCLE", 243},
37 | {"KEY_BRIGHTNESS_ZERO", 244},
38 | {"KEY_BRL_DOT1", 0x1f1},
39 | {"KEY_BRL_DOT10", 0x1fa},
40 | {"KEY_BRL_DOT2", 0x1f2},
41 | {"KEY_BRL_DOT3", 0x1f3},
42 | {"KEY_BRL_DOT4", 0x1f4},
43 | {"KEY_BRL_DOT5", 0x1f5},
44 | {"KEY_BRL_DOT6", 0x1f6},
45 | {"KEY_BRL_DOT7", 0x1f7},
46 | {"KEY_BRL_DOT8", 0x1f8},
47 | {"KEY_BRL_DOT9", 0x1f9},
48 | {"KEY_C", 46},
49 | {"KEY_CALC", 140},
50 | {"KEY_CALENDAR", 0x18d},
51 | {"KEY_CAMERA", 212},
52 | {"KEY_CAMERA_DOWN", 0x218},
53 | {"KEY_CAMERA_FOCUS", 0x210},
54 | {"KEY_CAMERA_LEFT", 0x219},
55 | {"KEY_CAMERA_RIGHT", 0x21a},
56 | {"KEY_CAMERA_UP", 0x217},
57 | {"KEY_CAMERA_ZOOMIN", 0x215},
58 | {"KEY_CAMERA_ZOOMOUT", 0x216},
59 | {"KEY_CANCEL", 223},
60 | {"KEY_CAPSLOCK", 58},
61 | {"KEY_CD", 0x17f},
62 | {"KEY_CHANNEL", 0x16b},
63 | {"KEY_CHANNELDOWN", 0x193},
64 | {"KEY_CHANNELUP", 0x192},
65 | {"KEY_CHAT", 216},
66 | {"KEY_CLEAR", 0x163},
67 | {"KEY_CLOSE", 206},
68 | {"KEY_CLOSECD", 160},
69 | {"KEY_COFFEE", 152},
70 | {"KEY_COMMA", 51},
71 | {"KEY_COMPOSE", 127},
72 | {"KEY_COMPUTER", 157},
73 | {"KEY_CONFIG", 171},
74 | {"KEY_CONNECT", 218},
75 | {"KEY_CONTEXT_MENU", 0x1b6},
76 | {"KEY_COPY", 133},
77 | {"KEY_CUT", 137},
78 | {"KEY_CYCLEWINDOWS", 154},
79 | {"KEY_D", 32},
80 | {"KEY_DASHBOARD", 204},
81 | {"KEY_DATABASE", 0x1aa},
82 | {"KEY_DELETE", 111},
83 | {"KEY_DELETEFILE", 146},
84 | {"KEY_DEL_EOL", 0x1c0},
85 | {"KEY_DEL_EOS", 0x1c1},
86 | {"KEY_DEL_LINE", 0x1c3},
87 | {"KEY_DIGITS", 0x19d},
88 | {"KEY_DIRECTION", 153},
89 | {"KEY_DIRECTORY", 0x18a},
90 | {"KEY_DISPLAYTOGGLE", 0x1af},
91 | {"KEY_DISPLAY_OFF", 245},
92 | {"KEY_DOCUMENTS", 235},
93 | {"KEY_DOLLAR", 0x1b2},
94 | {"KEY_DOT", 52},
95 | {"KEY_DOWN", 108},
96 | {"KEY_DVD", 0x185},
97 | {"KEY_E", 18},
98 | {"KEY_EDIT", 176},
99 | {"KEY_EDITOR", 0x1a6},
100 | {"KEY_EJECTCD", 161},
101 | {"KEY_EJECTCLOSECD", 162},
102 | {"KEY_EMAIL", 215},
103 | {"KEY_END", 107},
104 | {"KEY_ENTER", 28},
105 | {"KEY_EPG", 0x16d},
106 | {"KEY_EQUAL", 13},
107 | {"KEY_ESC", 1},
108 | {"KEY_EURO", 0x1b3},
109 | {"KEY_EXIT", 174},
110 | {"KEY_F", 33},
111 | {"KEY_F1", 59},
112 | {"KEY_F10", 68},
113 | {"KEY_F11", 87},
114 | {"KEY_F12", 88},
115 | {"KEY_F13", 183},
116 | {"KEY_F14", 184},
117 | {"KEY_F15", 185},
118 | {"KEY_F16", 186},
119 | {"KEY_F17", 187},
120 | {"KEY_F18", 188},
121 | {"KEY_F19", 189},
122 | {"KEY_F2", 60},
123 | {"KEY_F20", 190},
124 | {"KEY_F21", 191},
125 | {"KEY_F22", 192},
126 | {"KEY_F23", 193},
127 | {"KEY_F24", 194},
128 | {"KEY_F3", 61},
129 | {"KEY_F4", 62},
130 | {"KEY_F5", 63},
131 | {"KEY_F6", 64},
132 | {"KEY_F7", 65},
133 | {"KEY_F8", 66},
134 | {"KEY_F9", 67},
135 | {"KEY_FASTFORWARD", 208},
136 | {"KEY_FAVORITES", 0x16c},
137 | {"KEY_FILE", 144},
138 | {"KEY_FINANCE", 219},
139 | {"KEY_FIND", 136},
140 | {"KEY_FIRST", 0x194},
141 | {"KEY_FN", 0x1d0},
142 | {"KEY_FN_1", 0x1de},
143 | {"KEY_FN_2", 0x1df},
144 | {"KEY_FN_B", 0x1e4},
145 | {"KEY_FN_D", 0x1e0},
146 | {"KEY_FN_E", 0x1e1},
147 | {"KEY_FN_ESC", 0x1d1},
148 | {"KEY_FN_F", 0x1e2},
149 | {"KEY_FN_F1", 0x1d2},
150 | {"KEY_FN_F10", 0x1db},
151 | {"KEY_FN_F11", 0x1dc},
152 | {"KEY_FN_F12", 0x1dd},
153 | {"KEY_FN_F2", 0x1d3},
154 | {"KEY_FN_F3", 0x1d4},
155 | {"KEY_FN_F4", 0x1d5},
156 | {"KEY_FN_F5", 0x1d6},
157 | {"KEY_FN_F6", 0x1d7},
158 | {"KEY_FN_F7", 0x1d8},
159 | {"KEY_FN_F8", 0x1d9},
160 | {"KEY_FN_F9", 0x1da},
161 | {"KEY_FN_S", 0x1e3},
162 | {"KEY_FORWARD", 159},
163 | {"KEY_FORWARDMAIL", 233},
164 | {"KEY_FRAMEBACK", 0x1b4},
165 | {"KEY_FRAMEFORWARD", 0x1b5},
166 | {"KEY_FRONT", 132},
167 | {"KEY_G", 34},
168 | {"KEY_GAMES", 0x1a1},
169 | {"KEY_GOTO", 0x162},
170 | {"KEY_GRAPHICSEDITOR", 0x1a8},
171 | {"KEY_GRAVE", 41},
172 | {"KEY_GREEN", 0x18f},
173 | {"KEY_H", 35},
174 | {"KEY_HANGEUL", 122},
175 | {"KEY_HANJA", 123},
176 | {"KEY_HELP", 138},
177 | {"KEY_HENKAN", 92},
178 | {"KEY_HIRAGANA", 91},
179 | {"KEY_HOME", 102},
180 | {"KEY_HOMEPAGE", 172},
181 | {"KEY_HP", 211},
182 | {"KEY_I", 23},
183 | {"KEY_IMAGES", 0x1ba},
184 | {"KEY_INFO", 0x166},
185 | {"KEY_INSERT", 110},
186 | {"KEY_INS_LINE", 0x1c2},
187 | {"KEY_ISO", 170},
188 | {"KEY_J", 36},
189 | {"KEY_K", 37},
190 | {"KEY_KATAKANA", 90},
191 | {"KEY_KATAKANAHIRAGANA", 93},
192 | {"KEY_KBDILLUMDOWN", 229},
193 | {"KEY_KBDILLUMTOGGLE", 228},
194 | {"KEY_KBDILLUMUP", 230},
195 | {"KEY_KEYBOARD", 0x176},
196 | {"KEY_KP0", 82},
197 | {"KEY_KP1", 79},
198 | {"KEY_KP2", 80},
199 | {"KEY_KP3", 81},
200 | {"KEY_KP4", 75},
201 | {"KEY_KP5", 76},
202 | {"KEY_KP6", 77},
203 | {"KEY_KP7", 71},
204 | {"KEY_KP8", 72},
205 | {"KEY_KP9", 73},
206 | {"KEY_KPASTERISK", 55},
207 | {"KEY_KPCOMMA", 121},
208 | {"KEY_KPDOT", 83},
209 | {"KEY_KPENTER", 96},
210 | {"KEY_KPEQUAL", 117},
211 | {"KEY_KPJPCOMMA", 95},
212 | {"KEY_KPLEFTPAREN", 179},
213 | {"KEY_KPMINUS", 74},
214 | {"KEY_KPPLUS", 78},
215 | {"KEY_KPPLUSMINUS", 118},
216 | {"KEY_KPRIGHTPAREN", 180},
217 | {"KEY_KPSLASH", 98},
218 | {"KEY_L", 38},
219 | {"KEY_LANGUAGE", 0x170},
220 | {"KEY_LAST", 0x195},
221 | {"KEY_LEFT", 105},
222 | {"KEY_LEFTALT", 56},
223 | {"KEY_LEFTBRACE", 26},
224 | {"KEY_LEFTCTRL", 29},
225 | {"KEY_LEFTMETA", 125},
226 | {"KEY_LEFTSHIFT", 42},
227 | {"KEY_LINEFEED", 101},
228 | {"KEY_LIST", 0x18b},
229 | {"KEY_LOGOFF", 0x1b1},
230 | {"KEY_M", 50},
231 | {"KEY_MACRO", 112},
232 | {"KEY_MAIL", 155},
233 | {"KEY_MAX", 0x2ff},
234 | {"KEY_MEDIA", 226},
235 | {"KEY_MEDIA_REPEAT", 0x1b7},
236 | {"KEY_MEMO", 0x18c},
237 | {"KEY_MENU", 139},
238 | {"KEY_MESSENGER", 0x1ae},
239 | {"KEY_MHP", 0x16f},
240 | {"KEY_MICMUTE", 248},
241 | {"KEY_MINUS", 12},
242 | {"KEY_MODE", 0x175},
243 | {"KEY_MOVE", 175},
244 | {"KEY_MP3", 0x187},
245 | {"KEY_MSDOS", 151},
246 | {"KEY_MUHENKAN", 94},
247 | {"KEY_MUTE", 113},
248 | {"KEY_N", 49},
249 | {"KEY_NEW", 181},
250 | {"KEY_NEWS", 0x1ab},
251 | {"KEY_NEXT", 0x197},
252 | {"KEY_NEXTSONG", 163},
253 | {"KEY_NUMERIC_0", 0x200},
254 | {"KEY_NUMERIC_1", 0x201},
255 | {"KEY_NUMERIC_2", 0x202},
256 | {"KEY_NUMERIC_3", 0x203},
257 | {"KEY_NUMERIC_4", 0x204},
258 | {"KEY_NUMERIC_5", 0x205},
259 | {"KEY_NUMERIC_6", 0x206},
260 | {"KEY_NUMERIC_7", 0x207},
261 | {"KEY_NUMERIC_8", 0x208},
262 | {"KEY_NUMERIC_9", 0x209},
263 | {"KEY_NUMERIC_POUND", 0x20b},
264 | {"KEY_NUMERIC_STAR", 0x20a},
265 | {"KEY_NUMLOCK", 69},
266 | {"KEY_O", 24},
267 | {"KEY_OK", 0x160},
268 | {"KEY_OPEN", 134},
269 | {"KEY_OPTION", 0x165},
270 | {"KEY_P", 25},
271 | {"KEY_PAGEDOWN", 109},
272 | {"KEY_PAGEUP", 104},
273 | {"KEY_PASTE", 135},
274 | {"KEY_PAUSE", 119},
275 | {"KEY_PAUSECD", 201},
276 | {"KEY_PC", 0x178},
277 | {"KEY_PHONE", 169},
278 | {"KEY_PLAY", 207},
279 | {"KEY_PLAYCD", 200},
280 | {"KEY_PLAYER", 0x183},
281 | {"KEY_PLAYPAUSE", 164},
282 | {"KEY_POWER", 116},
283 | {"KEY_POWER2", 0x164},
284 | {"KEY_PRESENTATION", 0x1a9},
285 | {"KEY_PREVIOUS", 0x19c},
286 | {"KEY_PREVIOUSSONG", 165},
287 | {"KEY_PRINT", 210},
288 | {"KEY_PROG1", 148},
289 | {"KEY_PROG2", 149},
290 | {"KEY_PROG3", 202},
291 | {"KEY_PROG4", 203},
292 | {"KEY_PROGRAM", 0x16a},
293 | {"KEY_PROPS", 130},
294 | {"KEY_PVR", 0x16e},
295 | {"KEY_Q", 16},
296 | {"KEY_QUESTION", 214},
297 | {"KEY_R", 19},
298 | {"KEY_RADIO", 0x181},
299 | {"KEY_RECORD", 167},
300 | {"KEY_RED", 0x18e},
301 | {"KEY_REDO", 182},
302 | {"KEY_REFRESH", 173},
303 | {"KEY_REPLY", 232},
304 | {"KEY_RESERVED", 0},
305 | {"KEY_RESTART", 0x198},
306 | {"KEY_REWIND", 168},
307 | {"KEY_RFKILL", 247},
308 | {"KEY_RIGHT", 106},
309 | {"KEY_RIGHTALT", 100},
310 | {"KEY_RIGHTBRACE", 27},
311 | {"KEY_RIGHTCTRL", 97},
312 | {"KEY_RIGHTMETA", 126},
313 | {"KEY_RIGHTSHIFT", 54},
314 | {"KEY_RO", 89},
315 | {"KEY_S", 31},
316 | {"KEY_SAT", 0x17d},
317 | {"KEY_SAT2", 0x17e},
318 | {"KEY_SAVE", 234},
319 | {"KEY_SCALE", 120},
320 | {"KEY_SCREEN", 0x177},
321 | {"KEY_SCROLLDOWN", 178},
322 | {"KEY_SCROLLLOCK", 70},
323 | {"KEY_SCROLLUP", 177},
324 | {"KEY_SEARCH", 217},
325 | {"KEY_SELECT", 0x161},
326 | {"KEY_SEMICOLON", 39},
327 | {"KEY_SEND", 231},
328 | {"KEY_SENDFILE", 145},
329 | {"KEY_SETUP", 141},
330 | {"KEY_SHOP", 221},
331 | {"KEY_SHUFFLE", 0x19a},
332 | {"KEY_SLASH", 53},
333 | {"KEY_SLEEP", 142},
334 | {"KEY_SLOW", 0x199},
335 | {"KEY_SOUND", 213},
336 | {"KEY_SPACE", 57},
337 | {"KEY_SPELLCHECK", 0x1b0},
338 | {"KEY_SPORT", 220},
339 | {"KEY_SPREADSHEET", 0x1a7},
340 | {"KEY_STOP", 128},
341 | {"KEY_STOPCD", 166},
342 | {"KEY_SUBTITLE", 0x172},
343 | {"KEY_SUSPEND", 205},
344 | {"KEY_SWITCHVIDEOMODE", 227},
345 | {"KEY_SYSRQ", 99},
346 | {"KEY_T", 20},
347 | {"KEY_TAB", 15},
348 | {"KEY_TAPE", 0x180},
349 | {"KEY_TEEN", 0x19e},
350 | {"KEY_TEXT", 0x184},
351 | {"KEY_TIME", 0x167},
352 | {"KEY_TITLE", 0x171},
353 | {"KEY_TOUCHPAD_OFF", 0x214},
354 | {"KEY_TOUCHPAD_ON", 0x213},
355 | {"KEY_TOUCHPAD_TOGGLE", 0x212},
356 | {"KEY_TUNER", 0x182},
357 | {"KEY_TV", 0x179},
358 | {"KEY_TV2", 0x17a},
359 | {"KEY_TWEN", 0x19f},
360 | {"KEY_U", 22},
361 | {"KEY_UNDO", 131},
362 | {"KEY_UNKNOWN", 240},
363 | {"KEY_UP", 103},
364 | {"KEY_UWB", 239},
365 | {"KEY_V", 47},
366 | {"KEY_VCR", 0x17b},
367 | {"KEY_VCR2", 0x17c},
368 | {"KEY_VENDOR", 0x168},
369 | {"KEY_VIDEO", 0x189},
370 | {"KEY_VIDEOPHONE", 0x1a0},
371 | {"KEY_VIDEO_NEXT", 241},
372 | {"KEY_VIDEO_PREV", 242},
373 | {"KEY_VOICEMAIL", 0x1ac},
374 | {"KEY_VOLUMEDOWN", 114},
375 | {"KEY_VOLUMEUP", 115},
376 | {"KEY_W", 17},
377 | {"KEY_WAKEUP", 143},
378 | {"KEY_WIMAX", 246},
379 | {"KEY_WLAN", 238},
380 | {"KEY_WORDPROCESSOR", 0x1a5},
381 | {"KEY_WPS_BUTTON", 0x211},
382 | {"KEY_WWW", 150},
383 | {"KEY_X", 45},
384 | {"KEY_XFER", 147},
385 | {"KEY_Y", 21},
386 | {"KEY_YELLOW", 0x190},
387 | {"KEY_YEN", 124},
388 | {"KEY_Z", 44},
389 | {"KEY_ZENKAKUHANKAKU", 85},
390 | {"KEY_ZOOM", 0x174},
391 | {"KEY_ZOOMIN", 0x1a2},
392 | {"KEY_ZOOMOUT", 0x1a3},
393 | {"KEY_ZOOMRESET", 0x1a4},
394 | {"BTN_0", 0x100},
395 | {"BTN_1", 0x101},
396 | {"BTN_2", 0x102},
397 | {"BTN_3", 0x103},
398 | {"BTN_4", 0x104},
399 | {"BTN_5", 0x105},
400 | {"BTN_6", 0x106},
401 | {"BTN_7", 0x107},
402 | {"BTN_8", 0x108},
403 | {"BTN_9", 0x109},
404 | {"BTN_A", 0x130},
405 | {"BTN_B", 0x131},
406 | {"BTN_BACK", 0x116},
407 | {"BTN_BASE", 0x126},
408 | {"BTN_BASE2", 0x127},
409 | {"BTN_BASE3", 0x128},
410 | {"BTN_BASE4", 0x129},
411 | {"BTN_BASE5", 0x12a},
412 | {"BTN_BASE6", 0x12b},
413 | {"BTN_C", 0x132},
414 | {"BTN_DEAD", 0x12f},
415 | {"BTN_DIGI", 0x140},
416 | {"BTN_EXTRA", 0x114},
417 | {"BTN_FORWARD", 0x115},
418 | {"BTN_GAMEPAD", 0x130},
419 | {"BTN_GEAR_DOWN", 0x150},
420 | {"BTN_GEAR_UP", 0x151},
421 | {"BTN_JOYSTICK", 0x120},
422 | {"BTN_LEFT", 0x110},
423 | {"BTN_MIDDLE", 0x112},
424 | {"BTN_MISC", 0x100},
425 | {"BTN_MODE", 0x13c},
426 | {"BTN_MOUSE", 0x110},
427 | {"BTN_PINKIE", 0x125},
428 | {"BTN_RIGHT", 0x111},
429 | {"BTN_SELECT", 0x13a},
430 | {"BTN_SIDE", 0x113},
431 | {"BTN_START", 0x13b},
432 | {"BTN_STYLUS", 0x14b},
433 | {"BTN_STYLUS2", 0x14c},
434 | {"BTN_TASK", 0x117},
435 | {"BTN_THUMB", 0x121},
436 | {"BTN_THUMB2", 0x122},
437 | {"BTN_THUMBL", 0x13d},
438 | {"BTN_THUMBR", 0x13e},
439 | {"BTN_TL", 0x136},
440 | {"BTN_TL2", 0x138},
441 | {"BTN_TOOL_AIRBRUSH", 0x144},
442 | {"BTN_TOOL_BRUSH", 0x142},
443 | {"BTN_TOOL_DOUBLETAP", 0x14d},
444 | {"BTN_TOOL_FINGER", 0x145},
445 | {"BTN_TOOL_LENS", 0x147},
446 | {"BTN_TOOL_MOUSE", 0x146},
447 | {"BTN_TOOL_PEN", 0x140},
448 | {"BTN_TOOL_PENCIL", 0x143},
449 | {"BTN_TOOL_QUADTAP", 0x14f},
450 | {"BTN_TOOL_QUINTTAP", 0x148},
451 | {"BTN_TOOL_RUBBER", 0x141},
452 | {"BTN_TOOL_TRIPLETAP", 0x14e},
453 | {"BTN_TOP", 0x123},
454 | {"BTN_TOP2", 0x124},
455 | {"BTN_TOUCH", 0x14a},
456 | {"BTN_TR", 0x137},
457 | {"BTN_TR2", 0x139},
458 | {"BTN_TRIGGER", 0x120},
459 | {"BTN_TRIGGER_HAPPY", 0x2c0},
460 | {"BTN_TRIGGER_HAPPY1", 0x2c0},
461 | {"BTN_TRIGGER_HAPPY10", 0x2c9},
462 | {"BTN_TRIGGER_HAPPY11", 0x2ca},
463 | {"BTN_TRIGGER_HAPPY12", 0x2cb},
464 | {"BTN_TRIGGER_HAPPY13", 0x2cc},
465 | {"BTN_TRIGGER_HAPPY14", 0x2cd},
466 | {"BTN_TRIGGER_HAPPY15", 0x2ce},
467 | {"BTN_TRIGGER_HAPPY16", 0x2cf},
468 | {"BTN_TRIGGER_HAPPY17", 0x2d0},
469 | {"BTN_TRIGGER_HAPPY18", 0x2d1},
470 | {"BTN_TRIGGER_HAPPY19", 0x2d2},
471 | {"BTN_TRIGGER_HAPPY2", 0x2c1},
472 | {"BTN_TRIGGER_HAPPY20", 0x2d3},
473 | {"BTN_TRIGGER_HAPPY21", 0x2d4},
474 | {"BTN_TRIGGER_HAPPY22", 0x2d5},
475 | {"BTN_TRIGGER_HAPPY23", 0x2d6},
476 | {"BTN_TRIGGER_HAPPY24", 0x2d7},
477 | {"BTN_TRIGGER_HAPPY25", 0x2d8},
478 | {"BTN_TRIGGER_HAPPY26", 0x2d9},
479 | {"BTN_TRIGGER_HAPPY27", 0x2da},
480 | {"BTN_TRIGGER_HAPPY28", 0x2db},
481 | {"BTN_TRIGGER_HAPPY29", 0x2dc},
482 | {"BTN_TRIGGER_HAPPY3", 0x2c2},
483 | {"BTN_TRIGGER_HAPPY30", 0x2dd},
484 | {"BTN_TRIGGER_HAPPY31", 0x2de},
485 | {"BTN_TRIGGER_HAPPY32", 0x2df},
486 | {"BTN_TRIGGER_HAPPY33", 0x2e0},
487 | {"BTN_TRIGGER_HAPPY34", 0x2e1},
488 | {"BTN_TRIGGER_HAPPY35", 0x2e2},
489 | {"BTN_TRIGGER_HAPPY36", 0x2e3},
490 | {"BTN_TRIGGER_HAPPY37", 0x2e4},
491 | {"BTN_TRIGGER_HAPPY38", 0x2e5},
492 | {"BTN_TRIGGER_HAPPY39", 0x2e6},
493 | {"BTN_TRIGGER_HAPPY4", 0x2c3},
494 | {"BTN_TRIGGER_HAPPY40", 0x2e7},
495 | {"BTN_TRIGGER_HAPPY5", 0x2c4},
496 | {"BTN_TRIGGER_HAPPY6", 0x2c5},
497 | {"BTN_TRIGGER_HAPPY7", 0x2c6},
498 | {"BTN_TRIGGER_HAPPY8", 0x2c7},
499 | {"BTN_TRIGGER_HAPPY9", 0x2c8},
500 | {"BTN_WHEEL", 0x150},
501 | {"BTN_X", 0x133},
502 | {"BTN_Y", 0x134},
503 | {"BTN_Z", 0x135},
504 |
--------------------------------------------------------------------------------
/Clock/.gitignore:
--------------------------------------------------------------------------------
1 | /ApiKeys.py
2 | /Config-Chris.py
3 | /Config-Jean.py
4 | /Config-Kelly.py
5 | /Config.py
6 | /Config-jcwho.py
7 | /Config-Bedside.py
8 | /Config-7in-night.py
9 | /Config-7in-day.py
10 |
--------------------------------------------------------------------------------
/Clock/ApiKeys-example.py:
--------------------------------------------------------------------------------
1 | # change this to your API keys
2 | #
3 | # Map API keys -- only needs 1 of the following
4 | # Google Maps API key (if usemapbox is not set in Config)
5 | googleapi = 'YOUR GOOGLE MAPS API KEY'
6 | #
7 | # Mapbox API key (access_token) [if usemapbox is set in Config]
8 | mbapi = 'YOUR MAPBOX ACCESS TOKEN'
9 | #
10 | # If you want to use Openweathermap.org, uncomment and add appid
11 | owmapi = 'YOUR OPENWEATHERMAP APPID'
12 | #
13 | # If you want to use tomorrow.io, uncomment and add appid
14 | # also comment/remove owmapi if you're using tomorrow.io
15 | # tmapi = 'YOUR tomorrow.io API KEY'
16 |
--------------------------------------------------------------------------------
/Clock/Config-Example-Bedside.py:
--------------------------------------------------------------------------------
1 | from GoogleMercatorProjection import LatLng
2 | from PyQt4.QtGui import QColor
3 |
4 | # LOCATION(S)
5 | # Further radar configuration (zoom, marker location)
6 | # can be completed under the RADAR section
7 | primary_coordinates = 44.9764016, -93.2486732 # Change to your Lat/Lon
8 |
9 | # Location for weather report
10 | location = LatLng(primary_coordinates[0], primary_coordinates[1])
11 | # Default radar location
12 | primary_location = LatLng(primary_coordinates[0], primary_coordinates[1])
13 | noaastream = 'http://www.urberg.net:8000/tim273/edina'
14 | background = 'images/bb.jpg'
15 | squares1 = 'images/squares1-green.png'
16 | squares2 = 'images/squares2-green.png'
17 | icons = 'icons-darkgreen'
18 | textcolor = '#206225'
19 | clockface = 'images/clockface3-darkgreen.png'
20 | hourhand = 'images/hourhand-darkgreen.png'
21 | minhand = 'images/minhand-darkgreen.png'
22 | sechand = 'images/sechand-darkgreen.png'
23 |
24 | digital = 0 # 1 = Digtal Clock, 0 = Analog Clock
25 |
26 | digitalcolor = "#154018"
27 | digitalformat = "{0:%I:%M\n%S %p}" # The format of the time
28 | digitalsize = 200
29 | # The above example shows in this way:
30 | # https://github.com/n0bel/PiClock/blob/master/Documentation/Digital%20Clock%20v1.jpg
31 | # ( specifications of the time string are documented here:
32 | # https://docs.python.org/2/library/time.html#time.strftime )
33 |
34 | # digitalformat = "{0:%I:%M}"
35 | # digitalsize = 250
36 | # The above example shows in this way:
37 | # https://github.com/n0bel/PiClock/blob/master/Documentation/Digital%20Clock%20v2.jpg
38 |
39 |
40 | # 0 = English, 1 = Metric
41 | metric = 0
42 |
43 | # minutes
44 | radar_refresh = 10
45 |
46 | # minutes
47 | weather_refresh = 30
48 |
49 | # Wind in degrees instead of cardinal 0 = cardinal, 1 = degrees
50 | wind_degrees = 0
51 |
52 | # Font attribute applied globally
53 | fontattr = 'font-weight: bold; '
54 |
55 | # These are to dim the radar images, if needed.
56 | dimcolor = QColor('#103125')
57 | dimcolor.setAlpha(192)
58 |
59 | # Language Specific wording
60 | # DarkSky Language code
61 | # (https://darksky.net/dev/docs under lang=)
62 | Language = "EN"
63 |
64 | # The Python Locale for date/time (locale.setlocale)
65 | # '' for default Pi Setting
66 | # Locales must be installed in your Pi.. to check what is installed
67 | # locale -a
68 | # to install locales
69 | # sudo dpkg-reconfigure locales
70 | DateLocale = ''
71 |
72 | # Language specific wording
73 | LPressure = "Pressure "
74 | LHumidity = "Humidity "
75 | LWind = "Wind "
76 | Lgusting = " gusting "
77 | LFeelslike = "Feels like "
78 | LPrecip1hr = " Precip 1hr:"
79 | LToday = "Today: "
80 | LSunRise = "Sun Rise:"
81 | LSet = " Set: "
82 | LMoonPhase = " Moon Phase:"
83 | LInsideTemp = "Inside Temp "
84 | LRain = " Rain: "
85 | LSnow = " Snow: "
86 |
87 |
88 | # RADAR
89 | # By default, primary_location entered will be the center and marker of all
90 | # radar images.
91 | # To update centers/markers, change radar sections
92 | # below the desired lat/lon as:
93 | # -FROM-
94 | # primary_location,
95 | # -TO-
96 | # LatLng(44.9764016,-93.2486732),
97 | radar1 = {
98 | 'center': primary_location, # the center of your radar block
99 | 'zoom': 7, # this is a google maps zoom factor, bigger = smaller area
100 | 'style': 'mapbox/cj5l80zrp29942rmtg0zctjto', # Mapbox calls this Decimal
101 | 'markers': ( # google maps markers can be overlayed
102 | {
103 | 'location': primary_location,
104 | 'color': 'red',
105 | 'size': 'small',
106 | }, # dangling comma is on purpose.
107 | )
108 | }
109 |
110 |
111 | radar2 = {
112 | 'center': primary_location,
113 | 'zoom': 11,
114 | 'style': 'mapbox/cj5l80zrp29942rmtg0zctjto', # Mapbox calls this Decimal
115 | 'markers': (
116 | {
117 | 'location': primary_location,
118 | 'color': 'red',
119 | 'size': 'small',
120 | },
121 | )
122 | }
123 |
124 |
125 | radar3 = {
126 | 'center': primary_location,
127 | 'zoom': 7,
128 | 'style': 'mapbox/cj5l80zrp29942rmtg0zctjto', # Mapbox calls this Decimal
129 | 'markers': (
130 | {
131 | 'location': primary_location,
132 | 'color': 'red',
133 | 'size': 'small',
134 | },
135 | )
136 | }
137 |
138 | radar4 = {
139 | 'center': primary_location,
140 | 'zoom': 11,
141 | 'style': 'mapbox/cj5l80zrp29942rmtg0zctjto', # Mapbox calls this Decimal
142 | 'markers': (
143 | {
144 | 'location': primary_location,
145 | 'color': 'red',
146 | 'size': 'small',
147 | },
148 | )
149 | }
150 |
--------------------------------------------------------------------------------
/Clock/Config-Example-Berlin.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from GoogleMercatorProjection import LatLng
3 | from PyQt4.QtGui import QColor
4 |
5 | # LOCATION(S)
6 | # Further radar configuration (zoom, marker location) can be
7 | # completed under the RADAR section
8 | primary_coordinates = 52.5074559, 13.144557 # Change to your Lat/Lon
9 |
10 | location = LatLng(primary_coordinates[0], primary_coordinates[1])
11 | primary_location = LatLng(primary_coordinates[0], primary_coordinates[1])
12 | noaastream = ''
13 | background = 'images/berlin-at-night-mrwallpaper.jpg'
14 | squares1 = 'images/squares1-kevin.png'
15 | squares2 = 'images/squares2-kevin.png'
16 | icons = 'icons-lightblue'
17 | textcolor = '#bef'
18 | clockface = 'images/clockface3.png'
19 | hourhand = 'images/hourhand.png'
20 | minhand = 'images/minhand.png'
21 | sechand = 'images/sechand.png'
22 |
23 |
24 | digital = 0 # 1 = Digtal Clock, 0 = Analog Clock
25 |
26 | # Goes with light blue config (like the default one)
27 | digitalcolor = "#50CBEB"
28 | digitalformat = "{0:%I:%M\n%S %p}" # The format of the time
29 | digitalsize = 200
30 | # The above example shows in this way:
31 | # https://github.com/n0bel/PiClock/blob/master/Documentation/Digital%20Clock%20v1.jpg
32 | # ( specifications of the time string are documented here:
33 | # https://docs.python.org/2/library/time.html#time.strftime )
34 |
35 | # digitalformat = "{0:%I:%M}"
36 | # digitalsize = 250
37 | # The above example shows in this way:
38 | # https://github.com/n0bel/PiClock/blob/master/Documentation/Digital%20Clock%20v2.jpg
39 |
40 |
41 | metric = 1 # 0 = English, 1 = Metric
42 | radar_refresh = 10 # minutes
43 | weather_refresh = 30 # minutes
44 | # Wind in degrees instead of cardinal 0 = cardinal, 1 = degrees
45 | wind_degrees = 0
46 |
47 |
48 | # gives all text additional attributes using QT style notation
49 | # example: fontattr = 'font-weight: bold; '
50 | fontattr = ''
51 |
52 | # These are to dim the radar images, if needed.
53 | # see and try Config-Example-Bedside.py
54 | dimcolor = QColor('#000000')
55 | dimcolor.setAlpha(0)
56 |
57 | METAR=""
58 |
59 | # Language Specific wording
60 | # OpenWeatherMap Language code
61 | # (https://openweathermap.org/current#multi)
62 | Language = "DE"
63 |
64 | # The Python Locale for date/time (locale.setlocale)
65 | # '' for default Pi Setting
66 | # Locales must be installed in your Pi.. to check what is installed
67 | # locale -a
68 | # to install locales
69 | # sudo dpkg-reconfigure locales
70 | DateLocale = 'de_DE.utf-8'
71 |
72 | # Language specific wording
73 | # thanks to colonia27 for the language work
74 | LPressure = "Luftdruck "
75 | LHumidity = "Feuchtigkeit "
76 | LWind = "Wind "
77 | Lgusting = u" böen "
78 | LFeelslike = u"Gefühlt "
79 | LPrecip1hr = " Niederschlag 1h:"
80 | LToday = "Heute: "
81 | LSunRise = "Sonnenaufgang:"
82 | LSet = " unter: "
83 | LMoonPhase = " Mond Phase:"
84 | LInsideTemp = "Innen Temp "
85 | LRain = " Regen: "
86 | LSnow = " Schnee: "
87 | Lmoon1 = 'Neumond'
88 | Lmoon2 = 'Zunehmender Sichelmond'
89 | Lmoon3 = 'Zunehmender Halbmond'
90 | Lmoon4 = 'Zunehmender Dreiviertelmond'
91 | Lmoon5 = 'Vollmond '
92 | Lmoon6 = 'Abnehmender Dreiviertelmond'
93 | Lmoon7 = 'Abnehmender Halbmond'
94 | Lmoon8 = 'Abnehmender Sichelmond'
95 | # Language Specific terms for weather conditions
96 |
97 |
98 | Ltm_code_map = {
99 | 0: 'Unknown',
100 | 1000: "Klar",
101 | 1100: 'Teilweise klar',
102 | 1101: 'Teilweise Wolkig',
103 | 1102: 'Meist Wolkig',
104 | 1001: 'Wolkig',
105 | 2000: 'Nebel',
106 | 2100: 'Leichter Nebel',
107 | 4000: 'Nieselregen',
108 | 4001: 'Rain',
109 | 4200: 'Light Rain',
110 | 4201: 'Heavy Rain',
111 | 5000: 'Regen',
112 | 5001: 'Gewitter',
113 | 5100: 'Leichter Schnee',
114 | 5101: 'Starker Schneefall',
115 | 6000: 'Gefrierender Nieselregen',
116 | 6001: 'Gefrierender Regen',
117 | 6200: 'Gefrierender Regen',
118 | 6201: 'Gefrierender Regen',
119 | 7000: 'Eisstücke',
120 | 7101: 'Eisstücke',
121 | 7102: 'Eisstücke',
122 | 8000: 'Gewitter'
123 | }
124 |
125 |
126 | # RADAR
127 | # By default, primary_location entered will be the
128 | # center and marker of all radar images.
129 | # To update centers/markers, change radar sections
130 | # below the desired lat/lon as:
131 | # -FROM-
132 | # primary_location,
133 | # -TO-
134 | # LatLng(44.9764016,-93.2486732),
135 | radar1 = {
136 | 'center': primary_location, # the center of your radar block
137 | 'zoom': 7, # this is a google maps zoom factor, bigger = smaller area
138 | 'markers': ( # google maps markers can be overlayed
139 | {
140 | 'location': primary_location,
141 | 'color': 'red',
142 | 'size': 'small',
143 | }, # dangling comma is on purpose.
144 | )
145 | }
146 |
147 |
148 | radar2 = {
149 | 'center': primary_location,
150 | 'zoom': 11,
151 | 'markers': (
152 | {
153 | 'location': primary_location,
154 | 'color': 'red',
155 | 'size': 'small',
156 | },
157 | )
158 | }
159 |
160 |
161 | radar3 = {
162 | 'center': primary_location,
163 | 'zoom': 7,
164 | 'markers': (
165 | {
166 | 'location': primary_location,
167 | 'color': 'red',
168 | 'size': 'small',
169 | },
170 | )
171 | }
172 |
173 | radar4 = {
174 | 'center': primary_location,
175 | 'zoom': 11,
176 | 'markers': (
177 | {
178 | 'location': primary_location,
179 | 'color': 'red',
180 | 'size': 'small',
181 | },
182 | )
183 | }
184 |
--------------------------------------------------------------------------------
/Clock/Config-Example-London.py:
--------------------------------------------------------------------------------
1 | from GoogleMercatorProjection import LatLng # NOQA
2 | from PyQt4.QtGui import QColor
3 |
4 |
5 | # LOCATION(S)
6 | # Further radar configuration (zoom, marker location) can be
7 | # completed under the RADAR section
8 | primary_coordinates = 51.5286416, -0.1015987 # Change to your Lat/Lon
9 |
10 | location = LatLng(primary_coordinates[0], primary_coordinates[1])
11 | primary_location = LatLng(primary_coordinates[0], primary_coordinates[1])
12 | noaastream = '???'
13 | background = 'images/london-at-night-wallpapers.jpg'
14 | squares1 = 'images/squares1-kevin.png'
15 | squares2 = 'images/squares2-kevin.png'
16 | icons = 'icons-lightblue'
17 | textcolor = '#bef'
18 | clockface = 'images/clockface3.png'
19 | hourhand = 'images/hourhand.png'
20 | minhand = 'images/minhand.png'
21 | sechand = 'images/sechand.png'
22 |
23 |
24 | digital = 0 # 1 = Digtal Clock, 0 = Analog Clock
25 |
26 | # Goes with light blue config (like the default one)
27 | digitalcolor = "#50CBEB"
28 | digitalformat = "{0:%I:%M\n%S %p}" # The format of the time
29 | digitalsize = 200
30 | # The above example shows in this way:
31 | # https://github.com/n0bel/PiClock/blob/master/Documentation/Digital%20Clock%20v1.jpg
32 | # ( specifications of the time string are documented here:
33 | # https://docs.python.org/2/library/time.html#time.strftime )
34 |
35 | # digitalformat = "{0:%I:%M}"
36 | # digitalsize = 250
37 | # The above example shows in this way:
38 | # https://github.com/n0bel/PiClock/blob/master/Documentation/Digital%20Clock%20v2.jpg
39 |
40 |
41 | metric = 1 # 0 = English, 1 = Metric
42 | radar_refresh = 10 # minutes
43 | weather_refresh = 30 # minutes
44 | # Wind in degrees instead of cardinal 0 = cardinal, 1 = degrees
45 | wind_degrees = 0
46 |
47 | # gives all text additional attributes using QT style notation
48 | # example: fontattr = 'font-weight: bold; '
49 | fontattr = ''
50 |
51 | # These are to dim the radar images, if needed.
52 | # see and try Config-Example-Bedside.py
53 | dimcolor = QColor('#000000')
54 | dimcolor.setAlpha(0)
55 |
56 | METAR="EGLL" # LHR London Heathrow Airport
57 |
58 | # Language Specific wording
59 | # DarkSky Language code
60 | # (https://darksky.net/dev/docs under lang=)
61 | Language = "EN"
62 |
63 | # The Python Locale for date/time (locale.setlocale)
64 | # '' for default Pi Setting
65 | # Locales must be installed in your Pi.. to check what is installed
66 | # locale -a
67 | # to install locales
68 | # sudo dpkg-reconfigure locales
69 | DateLocale = ''
70 |
71 | # Language specific wording
72 | LPressure = "Pressure "
73 | LHumidity = "Humidity "
74 | LWind = "Wind "
75 | Lgusting = " gusting "
76 | LFeelslike = "Feels like "
77 | LPrecip1hr = " Precip 1hr:"
78 | LToday = "Today: "
79 | LSunRise = "Sun Rise:"
80 | LSet = " Set: "
81 | LMoonPhase = " Moon Phase:"
82 | LInsideTemp = "Inside Temp "
83 | LRain = " Rain: "
84 | LSnow = " Snow: "
85 |
86 |
87 | # RADAR
88 | # By default, primary_location entered will be the
89 | # center and marker of all radar images.
90 | # To update centers/markers,change radar sections below the desired lat/lon as:
91 | # -FROM-
92 | # primary_location,
93 | # -TO-
94 | # LatLng(44.9764016,-93.2486732),
95 | radar1 = {
96 | 'center': primary_location, # the center of your radar block
97 | 'zoom': 7, # this is a google maps zoom factor, bigger = smaller area
98 | 'markers': ( # google maps markers can be overlayed
99 | {
100 | 'location': primary_location,
101 | 'color': 'red',
102 | 'size': 'small',
103 | }, # dangling comma is on purpose.
104 | )
105 | }
106 |
107 |
108 | radar2 = {
109 | 'center': primary_location,
110 | 'zoom': 11,
111 | 'markers': (
112 | {
113 | 'location': primary_location,
114 | 'color': 'red',
115 | 'size': 'small',
116 | },
117 | )
118 | }
119 |
120 |
121 | radar3 = {
122 | 'center': primary_location,
123 | 'zoom': 7,
124 | 'markers': (
125 | {
126 | 'location': primary_location,
127 | 'color': 'red',
128 | 'size': 'small',
129 | },
130 | )
131 | }
132 |
133 | radar4 = {
134 | 'center': primary_location,
135 | 'zoom': 11,
136 | 'markers': (
137 | {
138 | 'location': primary_location,
139 | 'color': 'red',
140 | 'size': 'small',
141 | },
142 | )
143 | }
144 |
--------------------------------------------------------------------------------
/Clock/Config-Example.py:
--------------------------------------------------------------------------------
1 | from GoogleMercatorProjection import LatLng
2 | from PyQt4.QtGui import QColor
3 |
4 |
5 | # LOCATION(S)
6 | # Further radar configuration (zoom, marker location) can be
7 | # completed under the RADAR section
8 | primary_coordinates = 44.9764016, -93.2486732 # Change to your Lat/Lon
9 |
10 | location = LatLng(primary_coordinates[0], primary_coordinates[1])
11 | primary_location = LatLng(primary_coordinates[0], primary_coordinates[1])
12 | noaastream = 'http://www.urberg.net:8000/tim273/edina'
13 | background = 'images/clockbackground-kevin.png'
14 | squares1 = 'images/squares1-kevin.png'
15 | squares2 = 'images/squares2-kevin.png'
16 | icons = 'icons-lightblue'
17 | textcolor = '#bef'
18 | clockface = 'images/clockface3.png'
19 | hourhand = 'images/hourhand.png'
20 | minhand = 'images/minhand.png'
21 | sechand = 'images/sechand.png'
22 |
23 | # SlideShow
24 | useslideshow = 0 # 1 to enable, 0 to disable
25 | slide_time = 305 # in seconds, 3600 per hour
26 | slides = 'images/slideshow' # the path to your local images
27 | slide_bg_color = "#000" # https://htmlcolorcodes.com/ black #000
28 |
29 | digital = 0 # 1 = Digtal Clock, 0 = Analog Clock
30 |
31 | # Goes with light blue config (like the default one)
32 | digitalcolor = "#50CBEB"
33 | digitalformat = "{0:%I:%M\n%S %p}" # Format of the digital clock face
34 | digitalsize = 200
35 |
36 | # The above example shows in this way:
37 | # https://github.com/n0bel/PiClock/blob/master/Documentation/Digital%20Clock%20v1.jpg
38 | # ( specifications of the time string are documented here:
39 | # https://docs.python.org/2/library/time.html#time.strftime )
40 |
41 | # digitalformat = "{0:%I:%M}"
42 | # digitalsize = 250
43 | # The above example shows in this way:
44 | # https://github.com/n0bel/PiClock/blob/master/Documentation/Digital%20Clock%20v2.jpg
45 |
46 | digitalformat2 = "{0:%H:%M:%S}" # Format of the digital time on second screen
47 |
48 | clockUTC = 0 # Clock (analog/digital/top date) to display in UTC regardless of PiOS timezone
49 |
50 | usemapbox = 0 # Use Mapbox.com for maps, needs api key (mbapi in ApiKeys.py)
51 | metric = 0 # 0 = English, 1 = Metric
52 | radar_refresh = 10 # minutes
53 | weather_refresh = 30 # minutes
54 | # Wind in degrees instead of cardinal 0 = cardinal, 1 = degrees
55 | wind_degrees = 0
56 |
57 | # gives all text additional attributes using QT style notation
58 | # example: fontattr = 'font-weight: bold; '
59 | fontattr = ''
60 |
61 | # These are to dim the radar images, if needed.
62 | # see and try Config-Example-Bedside.py
63 | dimcolor = QColor('#000000')
64 | dimcolor.setAlpha(0)
65 |
66 | # Optional Current conditions replaced with observations from a METAR station
67 | # METAR is world wide, provided mostly for pilots
68 | # But data can be sparse outside US and Europe
69 | # If you're close to an international airport, you should find soemthing close
70 | # Find the closest METAR station with the following URL
71 | # https://www.aviationweather.gov/metar
72 | # scroll/zoom the map to find your closest station
73 | # or look up the ICAO code here:
74 | # https://airportcodes.aero/name
75 | METAR = ''
76 |
77 | # Language Specific wording
78 | # DarkSky Language code
79 | # (https://darksky.net/dev/docs under lang=)
80 | Language = "EN"
81 |
82 | # The Python Locale for date/time (locale.setlocale)
83 | # '' for default Pi Setting
84 | # Locales must be installed in your Pi.. to check what is installed
85 | # locale -a
86 | # to install locales
87 | # sudo dpkg-reconfigure locales
88 | DateLocale = ''
89 |
90 | # Language specific wording
91 | LPressure = "Pressure "
92 | LHumidity = "Humidity "
93 | LWind = "Wind "
94 | Lgusting = " gust "
95 | LFeelslike = "Feels like "
96 | LPrecip1hr = " Precip 1hr: "
97 | LToday = "Today: "
98 | LSunRise = "Sun Rise: "
99 | LSet = " Set: "
100 | LMoonPhase = " Moon: "
101 | LInsideTemp = "Inside Temp "
102 | LRain = " Rain: "
103 | LSnow = " Snow: "
104 | Lmoon1 = 'New Moon'
105 | Lmoon2 = 'Waxing Crescent'
106 | Lmoon3 = 'First Quarter'
107 | Lmoon4 = 'Waxing Gibbous'
108 | Lmoon5 = 'Full Moon'
109 | Lmoon6 = 'Waning Gibbous'
110 | Lmoon7 = 'Third Quarter'
111 | Lmoon8 = 'Waning Crecent'
112 | # Language Specific terms for weather conditions
113 | Lcc_code_map = {
114 | "freezing_rain_heavy": "Freezing Rain",
115 | "freezing_rain": "Freezing Rain",
116 | "freezing_rain_light": "Freezing Rain",
117 | "freezing_drizzle": "Freezing Drizzle",
118 | "ice_pellets_heavy": "Ice Pellets",
119 | "ice_pellets": "Ice Pellets",
120 | "ice_pellets_light": "Ice Pellets",
121 | "snow_heavy": "Heavy Snow",
122 | "snow": "Snow",
123 | "snow_light": "Light Snow",
124 | "flurries": "Flurries",
125 | "tstorm": "Thunder Storm",
126 | "rain_heavy": "Heavy Rain",
127 | "rain": "Rain",
128 | "rain_light": "Light Rain",
129 | "drizzle": "Drizzle",
130 | "fog_light": "Light Fog",
131 | "fog": "Fog",
132 | "cloudy": "Cloudy",
133 | "mostly_cloudy": "Mostly Cloudy",
134 | "partly_cloudy": "Partly Cloudy",
135 | "mostly_clear": "Mostly Clear",
136 | "clear": "Clear"
137 | }
138 |
139 | # RADAR
140 | # By default, primary_location entered will be the
141 | # center and marker of all radar images.
142 | # To update centers/markers, change radar sections
143 | # below the desired lat/lon as:
144 | # -FROM-
145 | # primary_location,
146 | # -TO-
147 | # LatLng(44.9764016,-93.2486732),
148 | radar1 = {
149 | 'center': primary_location, # the center of your radar block
150 | 'zoom': 7, # this is a maps zoom factor, bigger = smaller area
151 | 'style': 'mapbox/satellite-streets-v10', # optional style (mapbox only)
152 | 'color': 6, # rainviewer radar color style:
153 | # https://www.rainviewer.com/api.html#colorSchemes
154 | 'smooth': 1, # rainviewer radar smoothing
155 | 'snow': 1, # rainviewer radar show snow as different color
156 | 'markers': ( # google maps markers can be overlayed
157 | {
158 | 'visible': 1, # 0 = hide marker, 1 = show marker
159 | 'location': primary_location,
160 | 'color': 'red',
161 | 'size': 'small',
162 | 'image': 'teardrop-dot', # optional image from the markers folder
163 | }, # dangling comma is on purpose.
164 | )
165 | }
166 |
167 |
168 | radar2 = {
169 | 'center': primary_location,
170 | 'zoom': 11,
171 | 'style': 'mapbox/satellite-streets-v10',
172 | 'color': 6,
173 | 'smooth': 1,
174 | 'snow': 1,
175 | 'markers': (
176 | {
177 | 'visible': 1,
178 | 'location': primary_location,
179 | 'color': 'red',
180 | 'size': 'small',
181 | 'image': 'teardrop-dot',
182 | },
183 | )
184 | }
185 |
186 |
187 | radar3 = {
188 | 'center': primary_location,
189 | 'zoom': 7,
190 | 'style': 'mapbox/satellite-streets-v10',
191 | 'color': 6,
192 | 'smooth': 1,
193 | 'snow': 1,
194 | 'markers': (
195 | {
196 | 'visible': 1,
197 | 'location': primary_location,
198 | 'color': 'red',
199 | 'size': 'small',
200 | 'image': 'teardrop-dot',
201 | },
202 | )
203 | }
204 |
205 | radar4 = {
206 | 'center': primary_location,
207 | 'zoom': 11,
208 | 'style': 'mapbox/satellite-streets-v10',
209 | 'color': 6,
210 | 'smooth': 1,
211 | 'snow': 1,
212 | 'markers': (
213 | {
214 | 'visible': 1,
215 | 'location': primary_location,
216 | 'color': 'red',
217 | 'size': 'small',
218 | 'image': 'teardrop-dot',
219 | },
220 | )
221 | }
222 |
--------------------------------------------------------------------------------
/Clock/GoogleMercatorProjection.py:
--------------------------------------------------------------------------------
1 | # http://stackoverflow.com/
2 | # questions/12507274/how-to-get-bounds-of-a-google-static-map
3 | import math
4 | MERCATOR_RANGE = 256
5 |
6 |
7 | def bound(value, opt_min, opt_max):
8 | if (opt_min is not None):
9 | value = max(value, opt_min)
10 | if (opt_max is not None):
11 | value = min(value, opt_max)
12 | return value
13 |
14 |
15 | def degreesToRadians(deg):
16 | return deg * (math.pi / 180)
17 |
18 |
19 | def radiansToDegrees(rad):
20 | return rad / (math.pi / 180)
21 |
22 |
23 | class Point:
24 | def __init__(self, x=0, y=0):
25 | self.x = x
26 | self.y = y
27 |
28 | def __repr__(self):
29 | return "Point(%d,%d)" % (self.x, self.y)
30 |
31 | def __str__(self):
32 | return "(x=%d,y=%d)" % (self.x, self.y)
33 |
34 |
35 | class LatLng:
36 | def __init__(self, lt, ln):
37 | self.lat = lt
38 | self.lng = ln
39 |
40 | def __repr__(self):
41 | return "LatLng(%g,%g)" % (self.lat, self.lng)
42 |
43 | def __str__(self):
44 | return "(lat=%g,lng=%g)" % (self.lat, self.lng)
45 |
46 |
47 | class MercatorProjection:
48 |
49 | def __init__(self):
50 | self.pixelOrigin_ = Point(MERCATOR_RANGE / 2.0, MERCATOR_RANGE / 2.0)
51 | self.pixelsPerLonDegree_ = MERCATOR_RANGE / 360.0
52 | self.pixelsPerLonRadian_ = MERCATOR_RANGE / (2.0 * math.pi)
53 |
54 | def fromLatLngToPoint(self, latLng, opt_point=None):
55 | point = opt_point if opt_point is not None else Point(0, 0)
56 | origin = self.pixelOrigin_
57 | point.x = origin.x + latLng.lng * self.pixelsPerLonDegree_
58 | # NOTE(appleton): Truncating to 0.9999 effectively limits latitude to
59 | # 89.189.This is about a third of a tile past the edge of world tile
60 | siny = bound(math.sin(degreesToRadians(latLng.lat)), -0.9999, 0.9999)
61 | point.y = origin.y + 0.5 * math.log((1 + siny) / (1.0 - siny)) * \
62 | -self.pixelsPerLonRadian_
63 | return point
64 |
65 | def fromPointToLatLng(self, point):
66 | origin = self.pixelOrigin_
67 | lng = (point.x - origin.x) / self.pixelsPerLonDegree_
68 | latRadians = (point.y - origin.y) / -self.pixelsPerLonRadian_
69 | lat = radiansToDegrees(2.0 * math.atan(math.exp(latRadians)) -
70 | math.pi / 2.0)
71 | return LatLng(lat, lng)
72 |
73 |
74 | def getPoint(point, center, zoom, mapWidth, mapHeight):
75 | scale = 2.0**zoom
76 | proj = MercatorProjection()
77 | centerP = proj.fromLatLngToPoint(center)
78 | centerP.x = centerP.x * scale
79 | centerP.y = centerP.y * scale
80 | subjectP = proj.fromLatLngToPoint(point)
81 | subjectP.x = subjectP.x * scale
82 | subjectP.y = subjectP.y * scale
83 | return Point((subjectP.x - centerP.x) + mapWidth / 2.0,
84 | (subjectP.y - centerP.y) + mapHeight / 2.0)
85 |
86 |
87 | def getCorners(center, zoom, mapWidth, mapHeight):
88 | scale = 2.0**zoom
89 | proj = MercatorProjection()
90 | centerPx = proj.fromLatLngToPoint(center)
91 | SWPoint = Point(centerPx.x - (mapWidth / 2.0) / scale, centerPx.y +
92 | (mapHeight / 2.0) / scale)
93 | SWLatLon = proj.fromPointToLatLng(SWPoint)
94 | NEPoint = Point(centerPx.x + (mapWidth / 2.0) / scale, centerPx.y -
95 | (mapHeight / 2.0) / scale)
96 | NELatLon = proj.fromPointToLatLng(NEPoint)
97 | return {
98 | 'N': NELatLon.lat,
99 | 'E': NELatLon.lng,
100 | 'S': SWLatLon.lat,
101 | 'W': SWLatLon.lng,
102 | }
103 |
104 |
105 | # https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames
106 |
107 | def getTileXY(latLng, zoom):
108 | lat_rad = math.radians(latLng.lat)
109 | n = 2.0 ** zoom
110 | xtile = (latLng.lng + 180.0) / 360.0 * n
111 | ytile = ((1.0 - math.log(math.tan(lat_rad) +
112 | (1 / math.cos(lat_rad))) / math.pi) / 2.0 * n)
113 | return {
114 | 'X': xtile,
115 | 'Y': ytile
116 | }
117 |
--------------------------------------------------------------------------------
/Clock/icons-darkblue/.gitignore:
--------------------------------------------------------------------------------
1 | /Thumbs.db
2 |
--------------------------------------------------------------------------------
/Clock/icons-darkblue/clear-day.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/icons-darkblue/clear-day.png
--------------------------------------------------------------------------------
/Clock/icons-darkblue/clear-night.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/icons-darkblue/clear-night.png
--------------------------------------------------------------------------------
/Clock/icons-darkblue/cloudy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/icons-darkblue/cloudy.png
--------------------------------------------------------------------------------
/Clock/icons-darkblue/fog.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/icons-darkblue/fog.png
--------------------------------------------------------------------------------
/Clock/icons-darkblue/partly-cloudy-day.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/icons-darkblue/partly-cloudy-day.png
--------------------------------------------------------------------------------
/Clock/icons-darkblue/partly-cloudy-night.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/icons-darkblue/partly-cloudy-night.png
--------------------------------------------------------------------------------
/Clock/icons-darkblue/rain.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/icons-darkblue/rain.png
--------------------------------------------------------------------------------
/Clock/icons-darkblue/sleet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/icons-darkblue/sleet.png
--------------------------------------------------------------------------------
/Clock/icons-darkblue/snow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/icons-darkblue/snow.png
--------------------------------------------------------------------------------
/Clock/icons-darkblue/thunderstorm.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/icons-darkblue/thunderstorm.png
--------------------------------------------------------------------------------
/Clock/icons-darkblue/wind.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/icons-darkblue/wind.png
--------------------------------------------------------------------------------
/Clock/icons-darkgreen/clear-day.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/icons-darkgreen/clear-day.png
--------------------------------------------------------------------------------
/Clock/icons-darkgreen/clear-night.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/icons-darkgreen/clear-night.png
--------------------------------------------------------------------------------
/Clock/icons-darkgreen/cloudy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/icons-darkgreen/cloudy.png
--------------------------------------------------------------------------------
/Clock/icons-darkgreen/fog.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/icons-darkgreen/fog.png
--------------------------------------------------------------------------------
/Clock/icons-darkgreen/partly-cloudy-day.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/icons-darkgreen/partly-cloudy-day.png
--------------------------------------------------------------------------------
/Clock/icons-darkgreen/partly-cloudy-night.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/icons-darkgreen/partly-cloudy-night.png
--------------------------------------------------------------------------------
/Clock/icons-darkgreen/rain.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/icons-darkgreen/rain.png
--------------------------------------------------------------------------------
/Clock/icons-darkgreen/sleet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/icons-darkgreen/sleet.png
--------------------------------------------------------------------------------
/Clock/icons-darkgreen/snow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/icons-darkgreen/snow.png
--------------------------------------------------------------------------------
/Clock/icons-darkgreen/thunderstorm.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/icons-darkgreen/thunderstorm.png
--------------------------------------------------------------------------------
/Clock/icons-darkgreen/wind.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/icons-darkgreen/wind.png
--------------------------------------------------------------------------------
/Clock/icons-lightblue/.gitignore:
--------------------------------------------------------------------------------
1 | /Thumbs.db
2 |
--------------------------------------------------------------------------------
/Clock/icons-lightblue/clear-day.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/icons-lightblue/clear-day.png
--------------------------------------------------------------------------------
/Clock/icons-lightblue/clear-night.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/icons-lightblue/clear-night.png
--------------------------------------------------------------------------------
/Clock/icons-lightblue/cloudy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/icons-lightblue/cloudy.png
--------------------------------------------------------------------------------
/Clock/icons-lightblue/fog.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/icons-lightblue/fog.png
--------------------------------------------------------------------------------
/Clock/icons-lightblue/partly-cloudy-day.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/icons-lightblue/partly-cloudy-day.png
--------------------------------------------------------------------------------
/Clock/icons-lightblue/partly-cloudy-night.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/icons-lightblue/partly-cloudy-night.png
--------------------------------------------------------------------------------
/Clock/icons-lightblue/rain.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/icons-lightblue/rain.png
--------------------------------------------------------------------------------
/Clock/icons-lightblue/sleet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/icons-lightblue/sleet.png
--------------------------------------------------------------------------------
/Clock/icons-lightblue/snow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/icons-lightblue/snow.png
--------------------------------------------------------------------------------
/Clock/icons-lightblue/thunderstorm.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/icons-lightblue/thunderstorm.png
--------------------------------------------------------------------------------
/Clock/icons-lightblue/wind.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/icons-lightblue/wind.png
--------------------------------------------------------------------------------
/Clock/images/.gitignore:
--------------------------------------------------------------------------------
1 | /Thumbs.db
2 | /london-at-night-wallpapers.jpg
3 |
--------------------------------------------------------------------------------
/Clock/images/berlin-at-night-mrwallpaper.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/images/berlin-at-night-mrwallpaper.jpg
--------------------------------------------------------------------------------
/Clock/images/clockbackground-chris.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/images/clockbackground-chris.png
--------------------------------------------------------------------------------
/Clock/images/clockbackground-jean.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/images/clockbackground-jean.png
--------------------------------------------------------------------------------
/Clock/images/clockbackground-kelly.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/images/clockbackground-kelly.png
--------------------------------------------------------------------------------
/Clock/images/clockbackground-kevin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/images/clockbackground-kevin.png
--------------------------------------------------------------------------------
/Clock/images/clockbackground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/images/clockbackground.png
--------------------------------------------------------------------------------
/Clock/images/clockface3-darkblue.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/images/clockface3-darkblue.png
--------------------------------------------------------------------------------
/Clock/images/clockface3-darkgreen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/images/clockface3-darkgreen.png
--------------------------------------------------------------------------------
/Clock/images/clockface3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/images/clockface3.png
--------------------------------------------------------------------------------
/Clock/images/hourhand-darkblue.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/images/hourhand-darkblue.png
--------------------------------------------------------------------------------
/Clock/images/hourhand-darkgreen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/images/hourhand-darkgreen.png
--------------------------------------------------------------------------------
/Clock/images/hourhand.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/images/hourhand.png
--------------------------------------------------------------------------------
/Clock/images/minhand-darkblue.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/images/minhand-darkblue.png
--------------------------------------------------------------------------------
/Clock/images/minhand-darkgreen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/images/minhand-darkgreen.png
--------------------------------------------------------------------------------
/Clock/images/minhand.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/images/minhand.png
--------------------------------------------------------------------------------
/Clock/images/sechand-darkblue.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/images/sechand-darkblue.png
--------------------------------------------------------------------------------
/Clock/images/sechand-darkgreen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/images/sechand-darkgreen.png
--------------------------------------------------------------------------------
/Clock/images/sechand.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/images/sechand.png
--------------------------------------------------------------------------------
/Clock/images/slideshow/daniel-h-tong-1310255-unsplash.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/images/slideshow/daniel-h-tong-1310255-unsplash.jpg
--------------------------------------------------------------------------------
/Clock/images/slideshow/johannes-plenio-629984-unsplash.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/images/slideshow/johannes-plenio-629984-unsplash.jpg
--------------------------------------------------------------------------------
/Clock/images/slideshow/nasa-53888-unsplash.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/images/slideshow/nasa-53888-unsplash.jpg
--------------------------------------------------------------------------------
/Clock/images/slideshow/patrick-tomasso-1311143-unsplash.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/images/slideshow/patrick-tomasso-1311143-unsplash.jpg
--------------------------------------------------------------------------------
/Clock/images/slideshow/roman-bozhko-251398-unsplash.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/images/slideshow/roman-bozhko-251398-unsplash.jpg
--------------------------------------------------------------------------------
/Clock/images/slideshow/shot-by-cerqueira-1318576-unsplash.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/images/slideshow/shot-by-cerqueira-1318576-unsplash.jpg
--------------------------------------------------------------------------------
/Clock/images/squares1-green.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/images/squares1-green.png
--------------------------------------------------------------------------------
/Clock/images/squares1-jean.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/images/squares1-jean.png
--------------------------------------------------------------------------------
/Clock/images/squares1-kevin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/images/squares1-kevin.png
--------------------------------------------------------------------------------
/Clock/images/squares2-green.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/images/squares2-green.png
--------------------------------------------------------------------------------
/Clock/images/squares2-jean.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/images/squares2-jean.png
--------------------------------------------------------------------------------
/Clock/images/squares2-kevin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/images/squares2-kevin.png
--------------------------------------------------------------------------------
/Clock/markers/Readme.md:
--------------------------------------------------------------------------------
1 | # Custom markers
2 |
3 | This folder contains some sample map markers which are overlayed onto the
4 | radar maps as directed by your config file.
5 |
6 | markers.xcf is a gimp file containing several of the teardrop markers
7 | which I've made.
8 |
9 | Each image is 64x64 with the center of the image being placed on the location
10 | on the map.
11 |
--------------------------------------------------------------------------------
/Clock/markers/markers.xcf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/markers/markers.xcf
--------------------------------------------------------------------------------
/Clock/markers/teardrop-dot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/markers/teardrop-dot.png
--------------------------------------------------------------------------------
/Clock/markers/teardrop-family.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/markers/teardrop-family.png
--------------------------------------------------------------------------------
/Clock/markers/teardrop-home.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/markers/teardrop-home.png
--------------------------------------------------------------------------------
/Clock/markers/teardrop-school.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/markers/teardrop-school.png
--------------------------------------------------------------------------------
/Clock/markers/teardrop-work.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/markers/teardrop-work.png
--------------------------------------------------------------------------------
/Clock/markers/teardrop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Clock/markers/teardrop.png
--------------------------------------------------------------------------------
/Contributed/PiClock_neo-aeon-Clockface-FliegerB.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Contributed/PiClock_neo-aeon-Clockface-FliegerB.zip
--------------------------------------------------------------------------------
/Contributed/PiClock_neo-aeon-ClockfaceGuide-GIMP.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Contributed/PiClock_neo-aeon-ClockfaceGuide-GIMP.zip
--------------------------------------------------------------------------------
/Contributed/Readme.md:
--------------------------------------------------------------------------------
1 | # Things submitted by various PiClock Makers
2 |
3 | @neo-aeon submitted some cool things
4 |
5 | * A great analog clock face PiClock_neo-aeon-Clockface-FliegerB.zip
6 | * A clock face and hands making guide as gimp files.
7 |
8 | ### Personal thanks for the contriubtions.
9 |
--------------------------------------------------------------------------------
/Documentation/2015-06-11_10-36-44.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Documentation/2015-06-11_10-36-44.png
--------------------------------------------------------------------------------
/Documentation/Digital Clock v1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Documentation/Digital Clock v1.jpg
--------------------------------------------------------------------------------
/Documentation/Digital Clock v2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Documentation/Digital Clock v2.jpg
--------------------------------------------------------------------------------
/Documentation/Hardware.md:
--------------------------------------------------------------------------------
1 | # PiClock Hardware Guide
2 |
3 | ## Introduction
4 |
5 | I'm going to assume you know how to connect your Raspberry Pi, Power supply, Monitor,
6 | keyboard/mouse and Wifi or Wired Ethernet.
7 |
8 | What follows is the details of various optional hardware you can add to your Raspi
9 | to add features or make your clock cooler.
10 |
11 | If you want to experiment and learn about the various hardware, and possibly breadboard
12 | them first, I've included some decent guides for that. *However, you can just skip to the
13 | picture showing the hookup for the PiClock.*
14 |
15 | ## Raspberry Pi Models
16 |
17 | This hardware guide directly supports the following
18 |
19 | * Raspsbery Pi Revision 2 Model B
20 | * Raspberry Pi Revision 2 Model B
21 | * Raspberry Pi Model B+
22 | * Raspberry Pi 2 Model B
23 |
24 | Changes can be made, alternate pins (grounds/gpios) can be used to support
25 | other models, but this is left as an exercise for the reader.
26 |
27 |
28 | ## IR receiver (TSOP4838)
29 |
30 | There are many guides showing how to connect an IR receiver (and IR LEDs) to a Raspberry Pi.
31 | Here's one: http://www.raspberry-pi-geek.com/Archive/2014/03/Controlling-your-Pi-with-an-infrared-remote
32 |
33 | One thing to note is that most of these use GPIO18 (header pin 12). The Install instructions I've provided
34 | require the use of **GPIO3 (header pin 5)**. I've found this more convenient, usually sharing the connector
35 | with the DS18B20 temperature probe on GPIO4 (header pin 7).
36 |
37 | ```
38 | Raspi Header Pin TSOP4838 Pin
39 | 3.3V Pin 1 Pin 2
40 | Gnd Pin 9 Pin 1
41 | GPIO3 Pin 5 Pin 3
42 | ```
43 | 
44 |
45 | ## Inside Temperature ( DS18B20 )
46 |
47 | There are many guides showing how to connect and check one or more DS18B20s to
48 | a Raspberry Pi. Here's one: http://www.modmypi.com/blog/ds18b20-one-wire-digital-temperature-sensor-and-the-raspberry-pi
49 |
50 | ```
51 | Raspi Header Pin DS18B20 Pin
52 | 3.3V Pin 1 Pin 3
53 | Gnd Pin 9 Pin 1
54 | GPIO4 Pin 7 Pin 2
55 | ```
56 |
57 | 
58 |
59 |
60 | ## WS2818b RGB LED AmbiLight strip
61 |
62 | A good background guide about how WS2818b connects to the Raspberry Pi can be found here:
63 | https://learn.adafruit.com/neopixels-on-raspberry-pi/overview
64 |
65 | You might be tempted to connect the LED strip power to the 5V header pin of the Pi -- just don't!
66 | That pin can't pass enough current. With all the lights on full you may need an extra 2A to
67 | power a 30 LED string (NeoPixels for example come in 30, 60 and 144 LEDs per meter), so size
68 | your power supply accordingly.
69 |
70 | Everyone seems to recommend a level shift (3.3V to 5V) to drive the LEDs. I've found this to
71 | be unnecessary. It also seems that Adafruit recommends a 1000uF cap on the power supply, with
72 | the dubious explaination that it protects the LEDs from inrush surges. Again I don't botther.
73 | Meh... Your milage may vary. The data pin of the WS2818b string should be connected
74 | to GPIO18, header pin 12. Note the markings on the LED strip since they all are not pinned
75 | the same.
76 |
77 |
78 | 
79 |
80 | ## GPIO Buttons
81 |
82 | Up to 3 simple push button switches come preconfigured in the software. The switches are
83 | wired simply to connect a gpio pin to ground when pushed. The following line
84 | in startup.sh configure their function, and which GPIO they are located on.
85 | ```
86 | sudo Button/gpio-keys 23:KEY_SPACE 24:KEY_F2 25:KEY_UP &
87 | ```
88 | * GPIO23 (header pin 16) is mapped to a space (which flips pages on the clock.
89 | * GPIO24 (header pin 18) is mapped to F2 (which toggles the NOAA stream)
90 | * GPIO25 (header pin 22) is mapped to UP (which does nothing yet)
91 | * A convinient ground is on header pin 20.
92 |
93 | 
94 |
95 |
96 | ## Schematic of all connections
97 |
98 | For those that want to work from a schematic, I threw together a simple one
99 |
100 | 
101 |
102 |
103 |
104 |
--------------------------------------------------------------------------------
/Documentation/Hardware_Schematic.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Documentation/Hardware_Schematic.pdf
--------------------------------------------------------------------------------
/Documentation/Hardware_Schematic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Documentation/Hardware_Schematic.png
--------------------------------------------------------------------------------
/Documentation/Install-Clock-Only.md:
--------------------------------------------------------------------------------
1 | # Install Instructions for PiClock (Clock Only)
2 |
3 | This version of the instructions is for setting up just the clock
4 | itself, ignoring all the other options. It also assumes you have
5 | some OS already setup. So this is useful for setting up the
6 | clock on a desktop OS.
7 |
8 | # Prerequisites
9 |
10 | The minium requirements for a PiClock is pretty simple
11 | * Python 2.7+ (but not 3)
12 | * Python Qt4, known as PyQt4
13 | * git (as an alternative to git, you can pull the zip file from git hub
14 | (download button on the right side of the github project) then unzip it
15 | onto your system )
16 |
17 | Theses are available under Windows, Linux, and OSX OS's.
18 |
19 | How to get these installed on your choice of system I'll leave
20 | as an excersise for the reader.
21 |
22 | ### Get the PiClock software
23 | ```
24 | git clone https://github.com/n0bel/PiClock.git
25 | ```
26 | Alternatively, you can download a zip file of the github project.
27 |
28 | https://github.com/n0bel/PiClock/archive/master.zip, then unzip it.
29 |
30 |
31 | ### Configure the PiClock api keys
32 |
33 | The first is to set API keys for DarkSky and Google Maps.
34 | These are both free, unless you have large volume.
35 | The PiClock usage is well below the maximums imposed by the no cost api keys.
36 |
37 | #### DarkSky api keys
38 |
39 | DarkSky api keys are created at this link:
40 | https://darksky.net/dev
41 |
42 | #### Google Maps API key
43 |
44 | A Google Maps api key is _required_. (Requires credit card which won't be
45 | charged unless usage is great.)
46 |
47 | An intro to Google static maps api keys, and a link to creating your account and ApiKeys:
48 | https://developers.google.com/maps/documentation/maps-static/intro
49 | You'll require a google user and password. It'll also require a credit card.
50 | The credit card should not be charged, because my reading of https://cloud.google.com/maps-platform/pricing/sheet/ the $200.00 credit will
51 | apply, and your charges incurred will be for 31 map pulls per month will be
52 | $0.62 , if you reboot daily.
53 | You'll be required to create a "project" (maybe PiClock for a project name?)
54 | You need to then activate the key.
55 |
56 | _Protect your API keys._ You'd be surprised how many pastebin's are out
57 | there with valid API keys, because of people not being careful. If you post
58 | your keys somewhere, your usage will skyrocket, and your bill as well. Google
59 | has the ability to add referer, device and ip requirements on your api key. It
60 | can also allow you to limit an api key to specific applications only (static-maps)
61 | in this case. Also you might consider disabling all the other APIs on your
62 | project dashboard. Under the Billing section of things you can set up budgets
63 | and alerts. (Set to like $1.00)
64 |
65 |
66 | Now that you have your api keys...
67 |
68 | ```
69 | cd PiClock
70 | cd Clock
71 | cp ApiKeys-example.py ApiKeys.py
72 | [use your favorite editor] ApiKeys.py
73 | ```
74 | Put your api keys in the file as indicated
75 | ```
76 | #change this to your API keys
77 | # DarkSky API key
78 | dsapi = 'YOUR DARKSKY API KEY'
79 | # Google Maps API key
80 | googleapi = 'YOUR GOOGLE API KEY'
81 | ```
82 |
83 | ### Configure your PiClock
84 | here's were you tell PiClock where your weather should come from, and the
85 | radar map centers and markers.
86 |
87 | ```
88 | cd PiClock
89 | cd Clock
90 | cp Config-Example.py Config.py (copy on windows)
91 | [use your favorite editor] Config.py
92 | ```
93 |
94 | This file is a python script, subject to python rules and syntax.
95 | The configuration is a set of variables, objects and arrays,
96 | set up in python syntax. The positioning of the {} and () and ','
97 | are not arbitrary. If you're not familiar with python, use extra
98 | care not to disturb the format while changing the data.
99 |
100 | The first thing is to change the Latitudes and Longitudes you see to yours.
101 | They occur in several places. The first one in the file is where your weather
102 | forecast comes from. The others are where your radar images are centered
103 | and where the markers appear on those images. Markers are those little red
104 | location pointers.
105 |
106 | ### Run it!
107 |
108 | ```
109 | cd PiClock
110 | python PyQtPiClock.py
111 | ```
112 | After a few seconds, your screen should be covered by the PiClock YAY!
113 |
114 | There may be some output on the terminal screen as it executes.
115 | If everything works, it can be ignored. If for some reason the clock
116 | doesn't work, or maps are missing, etc the output may give a reason
117 | or reasons, which usually reference something to do with the config
118 | file (Config.py)
119 |
120 | ### First Use
121 |
122 | * The space bar or right or left arrows will change the page.
123 | * F2 will start and stop the NOAA weather radio stream
124 | * F4 will close the clock
125 |
126 |
127 | ### Updating to newer/updated versions
128 | Since we pulled the software from github originally, it can be updated
129 | using git and github.
130 | ```
131 | cd PiClock
132 | git pull
133 | python update.py
134 | ```
135 | This will automatically update any part(s) of the software that has changed.
136 | The update.py program will then convert any config files as needed.
137 |
--------------------------------------------------------------------------------
/Documentation/Install-Jessie.md:
--------------------------------------------------------------------------------
1 | # Install Instructions for PiClock
2 | ## For Raspbian Jessie
3 |
4 | PiClock and this install guide are based on Raspian Jessie
5 | last released on https://downloads.raspberrypi.org/raspbian/images/raspbian-2017-07-05/
6 | It will work with many raspbian versions, but you may have to add more packages,
7 | etc. That exercise is left for the reader.
8 |
9 | What follows is a step by step guide. If you start with a new clean raspbian
10 | image, it should just work. I'm assuming that you already know how to hook
11 | up your Raspi, monitor, and keyboard/mouse. If not, please do a web search
12 | regarding setting up the basic hardware for your Raspi.
13 |
14 | ### Download Raspbian Jessie and put it on an SD Card
15 |
16 | The image and instructions for doing this are on the following page:
17 | https://www.raspberrypi.org/downloads/
18 |
19 | ### First boot and configure
20 | A keyboard and mouse are really handy at this point.
21 | When you first boot your Pi, you'll be presented with the desktop.
22 | Navigate to Menu->Preferences->Raspberry Pi Configuration.
23 | Just change the Items below.
24 | - General Tab
25 | - Change User Password -- this will set the password for the use pi,
26 | for ssh logins.
27 | - Hostname: (Maybe set this to PiClock?)
28 | - Boot: To Desktop
29 | - Auto Login: Checked
30 | - Underscan: (Initally leave as default, but if your monitor has extra black area on the border, or bleeds off the edge, then change this)
31 | - Interfaces
32 | - 1-Wire Enable (for the inside temperature, DS18B20 if you're using it)
33 | - Internationalization Tab
34 | - Set Locale.
35 | - Set Language -- if you set language and country here, the date will automaticly be in your language
36 | -- other settings in Config.py (described later) control the language of the weather data
37 | - Set Country
38 | - Character Set: UTF-8
39 | - Set Timezone.
40 | - You'll want this to be correct, or the clock will be wrong.
41 | - Set Keyboard
42 | - Generally not needed, but good to check if you like the default
43 | - Set WiFi Country (may not always show up)
44 |
45 | Finish and let it reboot.
46 |
47 | I've found that sometimes on reboot, Jessie doesn't go back to desktop mode.
48 | If this is the case,
49 | ```
50 | sudo raspi-config
51 | ```
52 | and change the boot option to Desktop/Auto-login
53 |
54 | ### editing config.txt
55 |
56 | Log into your Pi, (either on the screen or via ssh)
57 |
58 | use nano to edit the boot config file
59 | ```
60 | sudo nano /boot/config.txt
61 | ```
62 | Be sure the lines
63 | ```
64 | dtoverlay=lirc-rpi,gpio_in_pin=3,gpio_out_pin=2
65 | dtoverlay=w1-gpio,gpiopin=4
66 | ```
67 | are in there somewhere, and occur only once.
68 | The default config has lirc-rpi commented out (# in front), don't forget to remove the #
69 | Also add the pin arguments just as shown above, if they are not already there.
70 |
71 | You're free to change the pins, but of course the hardware guide will need to
72 | be adjusted to match.
73 |
74 | use nano to edit the modules file
75 | ```
76 | sudo nano /etc/modules
77 | ```
78 | Be sure the lines
79 | ```
80 | lirc_rpi gpio_in_pin=3 gpio_out_pin=2
81 | w1-gpio
82 | ```
83 | are in there somewhere, and only occur once.
84 |
85 | reboot
86 | ```
87 | sudo reboot
88 | ```
89 |
90 | ### Get connected to the internet
91 |
92 | Either connect to your wired network, or setup wifi and verify you have
93 | internet access from the Pi
94 |
95 | ```
96 | ping github.com
97 | ```
98 | (remember ctrl-c aborts programs, like breaking out of ping, which will
99 | go on forever)
100 |
101 | ### Get all the software that PiClock needs.
102 |
103 | Become super user! (root) (trumpets play in the background) (ok, maybe
104 | just in my head)
105 | ```
106 | sudo su -
107 | ```
108 | update the repository
109 | ```
110 | apt-get update
111 | ```
112 | then get qt4 for python
113 | ```
114 | apt-get install python-qt4
115 | ```
116 | you may need to confirm some things, like:
117 | After this operation, 44.4 MB of additional disk space will be used.
118 | Do you want to continue [Y/n]? y
119 | Go ahead, say yes
120 |
121 | then get ws281x driver for python (optional for the NeoPixel LED Driver)
122 | ```
123 | pip install rpi_ws281x
124 | ```
125 | Someversions of Raspbian need python-dev to be installed as well, before
126 | rpi-ws281x can be installed. If the prevous command fails reporting
127 | a missing include file, then do this:
128 | ```
129 | apt-get install python-dev
130 | ```
131 | Then try the pip command again.
132 |
133 | then install more needed python libraries
134 | ```
135 | pip install python-dateutil --upgrade
136 | pip install tzlocal --upgrade
137 | pip install python-metar --upgrade
138 | ```
139 |
140 | then get unclutter (disables the mouse pointer when there's no activity)
141 | ```
142 | apt-get install unclutter
143 | ```
144 |
145 | ### Get the DS18B20 Temperature driver for Python (optional)
146 |
147 | (you must still be root [super user])
148 | ```
149 | git clone https://github.com/timofurrer/w1thermsensor.git && cd w1thermsensor
150 | python setup.py install
151 | ```
152 |
153 | ### Get Lirc driver for IR remote (optional)
154 |
155 | (you must still be root [super user])
156 | ```
157 | apt-get install lirc
158 | ```
159 |
160 | use nano to edit lirc hardware file
161 | ```
162 | sudo nano /etc/lirc/hardware.conf
163 | ```
164 | Be sure the LIRCD_ARGS line appears as follows
165 | ```
166 | LIRCD_ARGS="--uinput"
167 | ```
168 |
169 | Be sure the DRIVER line appears as follows
170 | ```
171 | DRIVER="default"
172 | ```
173 |
174 | Be sure the DEVICE line appears as follows
175 | ```
176 | DEVICE="/dev/lirc0"
177 | ```
178 |
179 | Be sure the MODULES line appears as follows
180 | ```
181 | MODULES="lirc_rpi"
182 | ```
183 |
184 | ### Get mpg123 (optional to play NOAA weather radio streams)
185 |
186 | (you must still be root [super user])
187 | ```
188 | apt-get install mpg123
189 | ```
190 |
191 | ### reboot
192 | To get some things running, and ensure the final config is right, we'll do
193 | a reboot
194 | ```
195 | reboot
196 | ```
197 |
198 | ### Get the PiClock software
199 | Log into your Pi, (either on the screen or via ssh) (NOT as root)
200 | You'll be in the home directory of the user pi (/home/pi) by default,
201 | and this is where we want to be.
202 | ```
203 | git clone https://github.com/n0bel/PiClock.git
204 | ```
205 | Once that is done, you'll have a new directory called PiClock
206 | A few commands are needed if you intend to use gpio buttons
207 | and the gpio-keys driver to compile it for the latest Raspbian:
208 | ```
209 | cd PiClock/Button
210 | make gpio-keys
211 | cd ../..
212 | ```
213 |
214 | ### Set up Lirc (IR Remote)
215 | If you're using the recommended IR Key Fob,
216 | https://www.google.com/search?q=Mini+Universal+Infrared+IR+TV+Set+Remote+Control+Keychain
217 | you can copy the lircd.conf file included in the distribution as follows:
218 | ```
219 | sudo cp IR/lircd.conf /etc/lirc/
220 | ```
221 | If you're using something else, you'll need to use irrecord, or load a remote file
222 | as found on http://lirc.org/
223 |
224 | The software expects 7 keys. KEY_F1, KEY_F2, KEY_F3, KEY_UP, KEY_DOWN, KEY_RIGHT
225 | and KEY_LEFT. Lirc takes these keys and injects them into linix as if they
226 | were typed from a keyboard. PyQPiClock.py then simply looks for normal keyboard
227 | events. Therefore of course, if you have a usb keyboard attached, those keys
228 | work too. On the key fob remote, F1 is power, F2 is mute and F3 is AV/TV.
229 |
230 | You should (must) verify your IR codes. I've included a program called IRCodes.pl
231 | which will verify that your lircd.conf is setup correctly.
232 | If you've rebooted after installing lircd.conf, you'll have to stop lirc first:
233 | ```
234 | sudo service lirc stop
235 | ```
236 | Then use the IRCodes.pl program as follows:
237 | ```
238 | perl IR/IRCodes.pl
239 | ```
240 | Yes, I reverted to perl.. I may redo it in Python one day.
241 |
242 | If you're using the recommended key fob remote, they come randomly programmed from
243 | the supplier. To program them you press and hold the mute button (the middle one)
244 | while watching the screen scroll through codes.
245 | When the screen shows
246 | ```
247 | ************ KEY_F2
248 | ```
249 | STOP! then try the other keys, be sure they all report KEY_UP, KEY_DOWN correctly.
250 | If not press and hold the mute button again, waiting for the asterisks and KEY_F2,
251 | then STOP again, try the other keys. Repeat the process until you have all the
252 | keys working.
253 |
254 | Ctrl-C to abort perl.
255 |
256 | then reboot
257 | ```
258 | sudo reboot
259 | ```
260 |
261 |
262 | ### Configure the PiClock api keys
263 |
264 | The first is to set API keys for DarkSky and Google Maps.
265 | These are both free, unless you have large volume.
266 | The PiClock usage is well below the maximums imposed by the no cost api keys.
267 |
268 | #### DarkSky api keys
269 |
270 | DarkSky api keys are created at this link:
271 | https://darksky.net/dev
272 |
273 | #### Google Maps API key
274 |
275 | A Google Maps api key is _required_. (Requires credit card which won't be
276 | charged unless usage is great.)
277 |
278 | An intro to Google static maps api keys, and a link to creating your account and ApiKeys:
279 | https://developers.google.com/maps/documentation/maps-static/intro
280 | You'll require a google user and password. It'll also require a credit card.
281 | The credit card should not be charged, because my reading of https://cloud.google.com/maps-platform/pricing/sheet/ the $200.00 credit will
282 | apply, and your charges incurred will be for 31 map pulls per month will be
283 | $0.62 , if you reboot daily.
284 | You'll be required to create a "project" (maybe PiClock for a project name?)
285 | You need to then activate the key.
286 |
287 | _Protect your API keys._ You'd be surprised how many pastebin's are out
288 | there with valid API keys, because of people not being careful. If you post
289 | your keys somewhere, your usage will skyrocket, and your bill as well. Google
290 | has the ability to add referer, device and ip requirements on your api key. It
291 | can also allow you to limit an api key to specific applications only (static-maps)
292 | in this case. Also you might consider disabling all the other APIs on your
293 | project dashboard. Under the Billing section of things you can set up budgets
294 | and alerts. (Set to like $1.00)
295 |
296 |
297 | Now that you have your api keys...
298 |
299 | ```
300 | cd PiClock
301 | cd Clock
302 | cp ApiKeys-example.py ApiKeys.py
303 | nano ApiKeys.py
304 | ```
305 | Put your api keys in the file as indicated
306 | ```
307 | #change this to your API keys
308 | # DarkSky API key
309 | dsapi = 'YOUR DARKSKY API KEY'
310 | # Google Maps API key
311 | googleapi = 'YOUR GOOGLE API KEY'
312 | ```
313 |
314 | ### Configure your PiClock
315 | here's were you tell PiClock where your weather should come from, and the
316 | radar map centers and markers.
317 |
318 | ```
319 | cd PiClock
320 | cd Clock
321 | cp Config-Example.py Config.py
322 | nano Config.py
323 | ```
324 |
325 | This file is a python script, subject to python rules and syntax.
326 | The configuration is a set of variables, objects and arrays,
327 | set up in python syntax. The positioning of the {} and () and ','
328 | are not arbitrary. If you're not familiar with python, use extra
329 | care not to disturb the format while changing the data.
330 |
331 | The first thing is to change the primary_coordinates to yours. That is really
332 | all that is manditory. Further customization of the radar maps can be done in
333 | the Radar section. There you can customize where your radar images are centered
334 | and where the markers appear on those images. Markers are those little red
335 | location pointers. Radar1 and 2 show on the first page, and 3 and 4 show on the
336 | second page of the display (here's a post of about that:
337 | https://www.facebook.com/permalink.php?story_fbid=1371576642857593&id=946361588712436&substory_index=0 )
338 |
339 | The second thing to change is your NOAA weather radio stream url. You can
340 | find it here: http://noaaweatherradio.org/ They don't put the .mp3 urls
341 | where they are easily accessable, so you need to use your browser to "View Page Source"
342 | in order to find the proper .mp3 url.
343 |
344 | At this point, I'd not recommend many other changes until you have tested
345 | and gotten it running.
346 |
347 | ### Run it!
348 | You'll need to be on the desktop, in a terminal program.
349 |
350 | ```
351 | cd PiClock
352 | sh startup.sh -n -s
353 | ```
354 | Your screen should be covered by the PiClock YAY!
355 |
356 | There will be some output on the terminal screen as startup.sh executes.
357 | If everything works, it can be ignored. If for some reason the clock
358 | doesn't work, or maps are missing, etc the output may give a reason
359 | or reasons, which usually reference something to do with the config
360 | file (Config.py)
361 |
362 | ### Logs
363 | The -s option causes no log files to be created, but
364 | instead logs to your terminal screen. If -s is omitted, logs are
365 | created in PiClock/Clock as PyQtPiClock.[1-7].log, which can also help
366 | you find issues. -s is normally omitted when started from the desktop icon
367 | or from crontab. Logs are then created for debugging auto starts.
368 |
369 | ### First Use
370 |
371 | * The space bar or right or left arrows will change the page.
372 | * F2 will start and stop the NOAA weather radio stream
373 | * F4 will close the clock
374 |
375 | If you're using the temperature feature AND you have multiple temperature sensors,
376 | you'll see the clock display: 000000283872:74.6 00000023489:65.4 or something similar.
377 | Note the numbers exactly. Use F4 to stop the clock,
378 | then..
379 | ```
380 | nano Temperature/TempNames.py
381 | ```
382 | Give each number a name, like is shown in the examples in that file
383 |
384 | ### setting the clock to auto start
385 | At this point the clock will only start when you manually start it, as
386 | described in the Run It section.
387 |
388 | Use only one autostart method.
389 | ## Autostart Method 1
390 | (NOT as root)
391 | ```
392 | cd PiClock
393 | chmod +x PiClock.desktop
394 | ln PiClock.desktop ~/Desktop
395 | mkdir ~/.config/autostart
396 | ln PiClock.desktop ~/.config/autostart
397 | ```
398 | This puts the a PiClock icon on your desktop. It also runs it when
399 | the desktop starts.
400 |
401 | ## Autostart Method 2
402 | To have it auto start on boot we need to do one more thing, edit the
403 | crontab file as follows: (it will automatically start nano) (NOT as root)
404 | ```
405 | crontab -e
406 | ```
407 | and add the following line:
408 | ```
409 | @reboot sh /home/pi/PiClock/startup.sh
410 | ```
411 | save the file
412 | and reboot to test
413 | ```
414 | sudo reboot
415 | ```
416 |
417 | ## Some notes about startup.sh
418 | startup.sh has a few options:
419 | * -n or --no-delay Don't delay on starting the clock right away (default is 45 seconds delay)
420 | * -d X or --delay X Delay X seconds before starting the clock
421 | * -m X or --message-delay X Delay X seconds while displaying a message on the desktop
422 |
423 | Startup also looks at the various optional PiClock items (Buttons, Temperature, NeoPixel, etc)
424 | and only starts those things that are configured to run. It also checks if they are already
425 | running, and refrains from starting them again if they are.
426 |
427 | ### Switching skins at certain times of the day
428 | This is optional, but if its just too bright at night, a switcher script will kill and restart
429 | PyQtPiClock with an alternate config.
430 |
431 | First you need to set up an alternate config. Config.py is the normal name, so perhaps Config-Night.py
432 | might be appropriate. For a dimmer display use Config-Example-Bedside.py as a guide.
433 |
434 | Now we'll tell our friend cron to run the switcher script (switcher.sh) on day/night cycles.
435 | Run the cron editor: (should *not* be roor)
436 | ```
437 | crontab -e
438 | ```
439 | Add lines similar to this:
440 | ```
441 | 0 8 * * * sh /home/pi/PiClock/switcher.sh Config
442 | 0 21 * * * sh /home/pi/PiClock/switcher.sh Config-Night
443 | ```
444 | The 8 there means 8am, to switch to the normal config, and the 21 means switch to Config-Night at 9pm.
445 | More info on crontab can be found here: https://en.wikipedia.org/wiki/Cron
446 |
447 | ### Setting the Pi to auto reboot every day
448 | This is optional but some may want their PiClock to reboot every day. I do this with mine,
449 | but it is probably not needed.
450 | ```
451 | sudo crontab -e
452 | ```
453 | add the following line
454 | ```
455 | 22 3 * * * /sbin/reboot
456 | ```
457 | save the file
458 |
459 | This sets the reboot to occur at 3:22am every day. Adjust as needed.
460 |
461 | ### Updating to newer/updated versions
462 | Since we pulled the software from github originally, it can be updated
463 | using git and github.
464 | ```
465 | cd PiClock
466 | git pull
467 | python update.py
468 | ```
469 | This will automatically update any part(s) of the software that has changed.
470 | The update.py program will then convert any config files as needed.
471 |
472 | You'll want to reboot after the update.
473 |
474 | Note: If you get errors because you've made changes to the base code you might need
475 | ```
476 | git reset --hard
477 | ```
478 | Backup your changes first!
479 | (This won't bother your Config.py nor ApiKeys.py because they are not tracked in git.
480 |
481 | Also, if you're using gpio-keys, you may need to remake it:
482 | ```
483 | cd PiClock/Buttons
484 | rm gpio-keys
485 | make gpio-keys
486 | ```
487 |
--------------------------------------------------------------------------------
/Documentation/Install.md:
--------------------------------------------------------------------------------
1 | # Install Instructions for PiClock
2 | ## For Raspbian Stretch
3 |
4 | PiClock and this install guide are based on Raspian Stretch downloaded from
5 | https://downloads.raspberrypi.org/raspbian/images/raspbian-2019-04-09/ I suggest using
6 | "Raspbian Stretch with desktop" It will work with many raspbian versions,
7 | but you may have to add more packages, etc. That exercise is left for the reader.
8 |
9 | What follows is a step by step guide. If you start with a new clean raspbian
10 | image, it should just work. I'm assuming that you already know how to hook
11 | up your Raspi, monitor, and keyboard/mouse. If not, please do a web search
12 | regarding setting up the basic hardware for your Raspi.
13 |
14 | ### Download Raspbian Stretch and put it on an SD Card
15 |
16 | Download the zip file, and unzip it. You'll have a .img file. You'll need
17 | an Imaging program like Win32 Disk Imager http://sourceforge.net/projects/win32diskimager/
18 |
19 | 
20 |
21 | Now, insert your SD card into your laptop/computer and browse to your image file.
22 |
23 | 
24 |
25 | **BEFORE YOU HIT WRITE - Please make sure that you have selected the correct device.
26 | Win32 will pick up any removable media including SSD's. The last thing you want to
27 | do is overwrite your computer's hard drive!**
28 |
29 | When you're happy that you have the **correct image**, and **correct device**, hit write.
30 |
31 | You'll get a warning message to confirm that you're happy to proceed.
32 | Hit yes, and the image will burn to your card.
33 |
34 |
35 | ### First boot and configure
36 | A keyboard and mouse are really handy at this point.
37 | When you first boot your Pi, you'll be presented with the desktop.
38 | Following this there will be several prompts to set things up, follow
39 | those prompts and set things as they make sense for you. Of course
40 | setting the proper timezone for a clock is key.
41 |
42 | Eventually the Pi will reboot, and you'll be back to the desktop.
43 | We need to configure a few more things.
44 |
45 | Navigate to Menu->Preferences->Raspberry Pi Configuration.
46 | Just change the Items below.
47 | - System Tab
48 | - Hostname: (Maybe set this to PiClock?)
49 | - Boot: To Desktop
50 | - Auto Login: Checked
51 | - Overscan: (Initally leave as default, but if your monitor has extra
52 | black area on the border, or bleeds off the edge, then change this)
53 | - Interfaces
54 | - 1-Wire Enable (for the inside temperature, DS18B20 if you're using it)
55 | - SSH is handy (if you'd like to connect to your clock from another computer)
56 | - VNC can be handy (same reason as ssh)
57 |
58 |
59 | Click ok, and allow it to reboot.
60 |
61 | ### editing config.txt
62 |
63 | (Only required if you will be using IR Remote control or DS18B20 temperature
64 | sensors)
65 | Log into your Pi, (either on the screen or via ssh)
66 |
67 | use nano to edit the boot config file
68 | ```
69 | sudo nano /boot/config.txt
70 | ```
71 | Be sure the lines
72 | ```
73 | dtoverlay=lirc-rpi,gpio_in_pin=3,gpio_out_pin=2
74 | dtoverlay=w1-gpio,gpiopin=4
75 | ```
76 | are in there somewhere, and occur only once.
77 | The default config has lirc-rpi commented out (# in front), don't forget to remove the #
78 | Also add the pin arguments just as shown above, if they are not already there.
79 |
80 | You're free to change the pins, but of course the hardware guide will need to
81 | be adjusted to match.
82 |
83 | use nano to edit the modules file
84 | ```
85 | sudo nano /etc/modules
86 | ```
87 | Be sure the lines
88 | ```
89 | lirc_rpi gpio_in_pin=3 gpio_out_pin=2
90 | w1-gpio
91 | ```
92 | are in there somewhere, and only occur once.
93 |
94 | reboot
95 | ```
96 | sudo reboot
97 | ```
98 |
99 | ### Get connected to the internet
100 |
101 | Verify you have internet access from the Pi
102 |
103 | ```
104 | ping github.com
105 | ```
106 | (remember ctrl-c aborts programs, like breaking out of ping, which will
107 | go on forever)
108 |
109 | ### Get all the software that PiClock needs.
110 |
111 | Become super user! (root) (trumpets play in the background) (ok, maybe
112 | just in my head)
113 | ```
114 | sudo su -
115 | ```
116 | update the repository
117 | ```
118 | apt-get update
119 | ```
120 | then get qt4 for python
121 | ```
122 | apt-get install python-qt4
123 | ```
124 | you may need to confirm some things, like:
125 | After this operation, 59.5 MB of additional disk space will be used.
126 | Do you want to continue [Y/n]? y
127 | Go ahead, say yes
128 |
129 | then get ws281x driver for python (optional for the NeoPixel LED Driver)
130 | ```
131 | pip install rpi_ws281x
132 | ```
133 | Someversions of Raspbian need python-dev to be installed as well, before
134 | rpi-ws281x can be installed. If the prevous command fails reporting
135 | a missing include file, then do this:
136 | ```
137 | apt-get install python-dev
138 | ```
139 | Then try the pip command again.
140 |
141 | then install more needed python libraries
142 | ```
143 | pip install python-dateutil --upgrade
144 | pip install tzlocal --upgrade
145 | pip install python-metar --upgrade
146 | ```
147 |
148 | then get unclutter (disables the mouse pointer when there's no activity)
149 | ```
150 | apt-get install unclutter
151 | ```
152 |
153 | ### Get the DS18B20 Temperature driver for Python (optional)
154 |
155 | (you must still be root [super user])
156 | ```
157 | git clone https://github.com/timofurrer/w1thermsensor.git && cd w1thermsensor
158 | python setup.py install
159 | ```
160 |
161 | ### Get Lirc driver for IR remote (optional)
162 |
163 | (you must still be root [super user])
164 | ```
165 | apt-get install lirc
166 | ```
167 |
168 | use nano to edit lirc options file
169 | ```
170 | sudo nano /etc/lirc/lirc_options.conf
171 | ```
172 | Be sure the uinput line appears as follows
173 | ```
174 | uinput = True
175 | ```
176 |
177 | Be sure the driver line appears as follows
178 | ```
179 | driver = default
180 |
181 | ```
182 |
183 | ### Get mpg123 (optional to play NOAA weather radio streams)
184 |
185 | (you must still be root [super user])
186 | ```
187 | apt-get install mpg123
188 | ```
189 |
190 | ### reboot
191 | To get some things running, and ensure the final config is right, we'll do
192 | a reboot
193 | ```
194 | reboot
195 | ```
196 |
197 | ### Get the PiClock software
198 | Log into your Pi, (either on the screen or via ssh) (NOT as root)
199 | You'll be in the home directory of the user pi (/home/pi) by default,
200 | and this is where we want to be. Note that the following command while
201 | itself not being case sensitive, further operation of PiClock may be
202 | affected if the upper and lower case of the command is not followed.
203 | ```
204 | git clone https://github.com/n0bel/PiClock.git
205 | ```
206 | (Optional for GPIO keys)
207 | Once that is done, you'll have a new directory called PiClock
208 | A few commands are needed if you intend to use gpio buttons
209 | and the gpio-keys driver to compile it for the latest Raspbian:
210 | ```
211 | cd PiClock/Button
212 | make gpio-keys
213 | cd ../..
214 | ```
215 |
216 | ### Set up Lirc (IR Remote)
217 |
218 | If you're using the recommended IR Key Fob,
219 | https://www.google.com/search?q=Mini+Universal+Infrared+IR+TV+Set+Remote+Control+Keychain
220 | you can copy the lircd.conf file included in the distribution as follows:
221 | ```
222 | sudo cp IR/lircd.conf /etc/lirc/lircd.conf.d/
223 | ```
224 | If you're using something else, you'll need to use irrecord, or load a remote file
225 | as found on http://lirc.org/
226 |
227 | The software expects 7 keys. KEY_F1, KEY_F2, KEY_F3, KEY_UP, KEY_DOWN, KEY_RIGHT
228 | and KEY_LEFT. Lirc takes these keys and injects them into linix as if they
229 | were typed from a keyboard. PyQPiClock.py then simply looks for normal keyboard
230 | events. Therefore of course, if you have a usb keyboard attached, those keys
231 | work too. On the key fob remote, F1 is power, F2 is mute and F3 is AV/TV.
232 |
233 | You should (must) verify your IR codes. I've included a program called IRCodes.pl
234 | which will verify that your lircd.conf is setup correctly.
235 | If you've rebooted after installing lircd.conf, you'll have to stop lirc first:
236 | ```
237 | sudo service lirc stop
238 | ```
239 | Then use the IRCodes.pl program as follows:
240 | ```
241 | perl IR/IRCodes.pl
242 | ```
243 | Yes, I reverted to perl.. I may redo it in Python one day.
244 |
245 | If you're using the recommended key fob remote, they come randomly programmed from
246 | the supplier. To program them you press and hold the mute button (the middle one)
247 | while watching the screen scroll through codes.
248 | When the screen shows
249 | ```
250 | ************ KEY_F2
251 | ```
252 | STOP! then try the other keys, be sure they all report KEY_UP, KEY_DOWN correctly.
253 | If not press and hold the mute button again, waiting for the asterisks and KEY_F2,
254 | then STOP again, try the other keys. Repeat the process until you have all the
255 | keys working.
256 |
257 | Ctrl-C to abort perl.
258 |
259 | then reboot
260 | ```
261 | sudo reboot
262 | ```
263 |
264 |
265 | ### Configure the PiClock api keys
266 |
267 | We need to set API keys for DarkSky and Mapbox or Google Maps.
268 | These are both unless you have large volume.
269 | The PiClock usage is well below the maximums imposed by the no cost api keys.
270 |
271 | #### DarkSky api keys
272 |
273 | DarkSky api keys are created at this link:
274 | https://darksky.net/dev
275 |
276 | #### Map API Key
277 |
278 | You have your choice of Mapbox or Google Maps to get your underlying maps from.
279 | You only need one or the other (mbapi or googleapi)
280 |
281 | #### Google Maps API key
282 |
283 | A Google Maps api key is required to use Google Maps.
284 | (Requires credit card which won't be charged unless usage is great.)
285 |
286 | An intro to Google static maps api keys, and a link to creating your account and ApiKeys:
287 | https://developers.google.com/maps/documentation/maps-static/intro
288 | You'll require a google user and password. It'll also require a credit card.
289 | The credit card should not be charged, because my reading of
290 | https://cloud.google.com/maps-platform/pricing/sheet/ the $200.00 credit will
291 | apply, and your charges incurred will be for 31 map pulls per month will be
292 | $0.62 , if you reboot daily.
293 | You'll be required to create a "project" (maybe PiClock for a project name?)
294 | You need to then activate the key.
295 |
296 | _Protect your API keys._ You'd be surprised how many pastebin's are out
297 | there with valid API keys, because of people not being careful. _If you post
298 | your keys somewhere, your usage will skyrocket, and your bill as well._ Google
299 | has the ability to add referer, device and ip requirements on your api key. It
300 | can also allow you to limit an api key to specific applications only (static-maps)
301 | in this case. Also you might consider disabling all the other APIs on your
302 | project dashboard. Under the Billing section of things you can set up budgets
303 | and alerts. (Set to like $1.00)
304 |
305 | #### Mapbox api keys
306 |
307 | Mapbox api keys (access tokens) are created by signing up at this link:
308 |
309 | https://www.mapbox.com/signup/
310 |
311 |
312 |
313 | Now that you have your api keys...
314 |
315 | ```
316 | cd PiClock
317 | cd Clock
318 | cp ApiKeys-example.py ApiKeys.py
319 | nano ApiKeys.py
320 | ```
321 | Put your api keys in the file as indicated
322 | ```
323 | #change this to your API keys
324 | # DarkSky API key
325 | dsapi = 'YOUR DARKSKY API KEY'
326 | # Map API keys -- only needs 1 of the following
327 | # Google Maps API key (if usemapbox is not set in Config)
328 | googleapi = 'YOUR GOOGLE MAPS API KEY'
329 | # Mapbox API key (access_token) [if usemapbox is set in Config]
330 | mbapi = 'YOUR MAPBOX ACCESS TOKEN'
331 | ```
332 |
333 | ### Configure your PiClock
334 | here's were you tell PiClock where your weather should come from, and the
335 | radar map centers and markers.
336 |
337 | ```
338 | cd PiClock
339 | cd Clock
340 | cp Config-Example.py Config.py
341 | nano Config.py
342 | ```
343 |
344 | This file is a python script, subject to python rules and syntax.
345 | The configuration is a set of variables, objects and arrays,
346 | set up in python syntax. The positioning of the {} and () and ','
347 | are not arbitrary. If you're not familiar with python, use extra
348 | care not to disturb the format while changing the data.
349 |
350 | The first thing is to change the primary_coordinates to yours. That is really
351 | all that is manditory. Further customization of the radar maps can be done in
352 | the Radar section. There you can customize where your radar images are centered
353 | and where the markers appear on those images. Markers are those little red
354 | location pointers. Radar1 and 2 show on the first page, and 3 and 4 show on the
355 | second page of the display (here's a post of about that:
356 | https://www.facebook.com/permalink.php?story_fbid=1371576642857593&id=946361588712436&substory_index=0 )
357 |
358 | The second thing to change is your NOAA weather radio stream url. You can
359 | find it here: http://noaaweatherradio.org/ They don't put the .mp3 urls
360 | where they are easily accessable, so you need to use your browser to "View Page Source"
361 | in order to find the proper .mp3 url.
362 |
363 | At this point, I'd not recommend many other changes until you have tested
364 | and gotten it running.
365 |
366 | ### Run it!
367 | You'll need to be on the desktop, in a terminal program.
368 |
369 | ```
370 | cd PiClock
371 | sh startup.sh -n -s
372 | ```
373 | Your screen should be covered by the PiClock YAY!
374 |
375 | There will be some output on the terminal screen as startup.sh executes.
376 | If everything works, it can be ignored. If for some reason the clock
377 | doesn't work, or maps are missing, etc the output may give a reason
378 | or reasons, which usually reference something to do with the config
379 | file (Config.py)
380 |
381 | ### Logs
382 | The -s option causes no log files to be created, but
383 | instead logs to your terminal screen. If -s is omitted, logs are
384 | created in PiClock/Clock as PyQtPiClock.[1-7].log, which can also help
385 | you find issues. -s is normally omitted when started from the desktop icon
386 | or from crontab. Logs are then created for debugging auto starts.
387 |
388 | ### First Use
389 |
390 | * The space bar or right or left arrows will change the page.
391 | * F2 will start and stop the NOAA weather radio stream
392 | * F4 will close the clock
393 |
394 | If you're using the temperature feature AND you have multiple temperature sensors,
395 | you'll see the clock display: 000000283872:74.6 00000023489:65.4 or something similar.
396 | Note the numbers exactly. Use F4 to stop the clock,
397 | then..
398 | ```
399 | nano Temperature/TempNames.py
400 | ```
401 | Give each number a name, like is shown in the examples in that file
402 |
403 | ### setting the clock to auto start
404 | At this point the clock will only start when you manually start it, as
405 | described in the Run It section.
406 |
407 | Use only one autostart method.
408 | ## Autostart Method 1
409 | (NOT as root)
410 | ```
411 | cd PiClock
412 | chmod +x PiClock.desktop
413 | ln PiClock.desktop ~/Desktop
414 | mkdir ~/.config/autostart
415 | ln PiClock.desktop ~/.config/autostart
416 | ```
417 | This puts the a PiClock icon on your desktop. It also runs it when
418 | the desktop starts.
419 |
420 | ## Autostart Method 2
421 | To have it auto start on boot we need to do one more thing, edit the
422 | crontab file as follows: (it will automatically start nano) (NOT as root)
423 | ```
424 | crontab -e
425 | ```
426 | and add the following line:
427 | ```
428 | @reboot sh /home/pi/PiClock/startup.sh
429 | ```
430 | save the file
431 | and reboot to test
432 | ```
433 | sudo reboot
434 | ```
435 |
436 | ## Some notes about startup.sh
437 | startup.sh has a few options:
438 | * -n or --no-delay Don't delay on starting the clock right away (default is 45 seconds delay)
439 | * -d X or --delay X Delay X seconds before starting the clock
440 | * -m X or --message-delay X Delay X seconds while displaying a message on the desktop
441 |
442 | Startup also looks at the various optional PiClock items (Buttons, Temperature, NeoPixel, etc)
443 | and only starts those things that are configured to run. It also checks if they are already
444 | running, and refrains from starting them again if they are.
445 |
446 | ### Switching skins at certain times of the day
447 | This is optional, but if its just too bright at night, a switcher script will kill and restart
448 | PyQtPiClock with an alternate config.
449 |
450 | First you need to set up an alternate config. Config.py is the normal name, so perhaps Config-Night.py
451 | might be appropriate. For a dimmer display use Config-Example-Bedside.py as a guide.
452 |
453 | First we must make switcher.sh executable (git removes the x flags)
454 | ```
455 | cd PiClock
456 | chmod +x switcher.sh
457 | ```
458 | Now we'll tell our friend cron to run the switcher script (switcher.sh) on day/night cycles.
459 | Run the cron editor: (should *not* be roor)
460 | ```
461 | crontab -e
462 | ```
463 | Add lines similar to this:
464 | ```
465 | 0 8 * * * sh /home/pi/PiClock/switcher.sh Config
466 | 0 21 * * * sh /home/pi/PiClock/switcher.sh Config-Night
467 | ```
468 | The 8 there means 8am, to switch to the normal config, and the 21 means switch to Config-Night at 9pm.
469 | More info on crontab can be found here: https://en.wikipedia.org/wiki/Cron
470 |
471 | ### Setting the Pi to auto reboot every day
472 | This is optional but some may want their PiClock to reboot every day. I do this with mine,
473 | but it is probably not needed.
474 | ```
475 | sudo crontab -e
476 | ```
477 | add the following line
478 | ```
479 | 22 3 * * * /sbin/reboot
480 | ```
481 | save the file
482 |
483 | This sets the reboot to occur at 3:22am every day. Adjust as needed.
484 |
485 | ### Updating to newer/updated versions
486 | Since we pulled the software from github originally, it can be updated
487 | using git and github.
488 | ```
489 | cd PiClock
490 | git pull
491 | python update.py
492 | ```
493 | This will automatically update any part(s) of the software that has changed.
494 | The update.py program will then convert any config files as needed.
495 |
496 | You'll want to reboot after the update.
497 |
498 | Note: If you get errors because you've made changes to the base code you might need
499 | ```
500 | git diff
501 | ```
502 | To see your changes, so you can back them up
503 |
504 | Then this will update to the current version
505 | ```
506 | git reset --hard
507 | ```
508 | (This won't bother your Config.py nor ApiKeys.py because they are not tracked in git.
509 |
510 | Also, if you're using gpio-keys, you may need to remake it:
511 | ```
512 | cd PiClock/Button
513 | rm gpio-keys
514 | make gpio-keys
515 | ```
516 |
517 | ### Updating on very old Raspbian versions
518 | If your log shows error messages regarding dateutil or tzlocal you'll need
519 | to install them using pip. Since these are very old versions you'll need to
520 | download them.
521 |
522 | These steps worked on my old Raspbian GNU/Linux 7 (wheezy), which I installed in
523 | 2015.
524 |
525 | ```
526 | sudo su - # becoming root
527 | wget https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl
528 | wget https://files.pythonhosted.org/packages/36/7a/87837f39d0296e723bb9b62bbb257d0355c7f6128853c78955f57342a56d/python_dateutil-2.8.2-py2.py3-none-any.whl
529 | wget https://files.pythonhosted.org/packages/61/28/1d3920e4d1d50b19bc5d24398a7cd85cc7b9a75a490570d5a30c57622d34/pytz-2018.9-py2.py3-none-any.whl
530 | wget https://files.pythonhosted.org/packages/cb/89/e3687d3ed99bc882793f82634e9824e62499fdfdc4b1ae39e211c5b05017/tzlocal-1.5.1.tar.gz
531 | wget https://files.pythonhosted.org/packages/53/97/7cc5be0d41443ba5d6b700e749f43716ff87a7ce2dbd87e92fe97e04c369/python-metar-1.4.0.tar.gz
532 |
533 | pip install --trusted-host pypi.org --trusted-host files.pythonhosted.org six-1.16.0-py2.py3-none-any.whl
534 | pip install --trusted-host pypi.org --trusted-host files.pythonhosted.org python_dateutil-2.8.2-py2.py3-none-any.whl
535 | pip install --trusted-host pypi.org --trusted-host files.pythonhosted.org pytz-2018.9-py2.py3-none-any.whl
536 | pip install --trusted-host pypi.org --trusted-host files.pythonhosted.org tzlocal-1.5.1.tar.gz
537 | pip install --trusted-host pypi.org --trusted-host files.pythonhosted.org python-metar-1.4.0.tar.gz
538 |
539 | ```
540 |
541 |
--------------------------------------------------------------------------------
/Documentation/NeoPixel.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Documentation/NeoPixel.jpg
--------------------------------------------------------------------------------
/Documentation/Overview.md:
--------------------------------------------------------------------------------
1 | # Overview of the PiClock
2 |
3 | ## Introduction
4 |
5 | The PiClock is a clock (duh), weather forcast, and radar map display
6 | based on the Raspberry Pi and a display monitor. The display monitor is
7 | assumed to be an HDMI monitor, but it will probably (possibly) work with
8 | the composite output as well, but this is not a design goal. The main
9 | program (Clock/PyQtPiClock.py) will also run on Windows, Mac, and Linux,
10 | as long as python 2.7+ and PyQt4 is installed.
11 |
12 | ~~The Weather data comes from DarkSky using their API ( http://darksky.net/dev/ ).
13 | The maps are from Mapbox ( https://mapbox.com/ ) Google Maps API.
14 | **You must get API Keys from DarkSky and Mapbox or Google in order to make
15 | this work.** It is free for low usage such as this application.~~
16 |
17 | The Weather data comes from OpenWeatherMap or Tomorrow.io using their API.
18 | The maps are from Mapbox ( https://mapbox.com/ ) or Google Maps API.
19 | **You must get API Keys from OpenWeatherMap or Tomorrow.io and Mapbox
20 | or Google in order to makethis work.** It is free for low usage such
21 | as this application.
22 |
23 |
24 | The PiClock can be customized with several supported additional things:
25 | * RGB LED strips (NeoPixel) to create an ambilight effect
26 | * gpio buttons for changing the view
27 | * IR Remote Control for changing the view
28 | * Streaming the NOAA weather radio stream for your area
29 |
30 | The power usage I've measured is about 35watts with a 19" HDMI Monitor, 27 LEDs and the Pi.
31 | The LEDs contributed 3 or so watts, and I think the Pi is about 2-3 Watts normally.
32 |
33 | This is the basic PiClock, with some options added.
34 | 
35 |
36 | I chose to remove the plastic frame from my monitor and mount the Pi directly
37 | on it, as well as tap power from the display's power supply.
38 | 
39 |
40 | I've made it work on multiple platforms and form factors.
41 | 
42 |
43 | And I've made some for friends and family with different customizations.
44 | 
45 |
46 |
47 | ## List of materials
48 |
49 | So what do you need to build a PiClock?
50 |
51 | * A Raspberry Pi (revision 2) Model B, or B+ or Pi 2 Model B
52 | * A Display Monitor & Cable
53 | * Power Supply (or if you're ambitious tap your display power supply,
54 | you'll probably need a switching down regulator to 5v) Remember
55 | the Pi likes something that can source up to 2A.
56 | * A USB Keyboard and Mouse for setup (if you want something small
57 | and semi-permanent, I've had good luck with this:
58 | https://www.google.com/search?q=iPazzPort+2.4G+Mini+Wireless+Keyboard
59 | I like the one with the mousepad on the side)
60 | * USB Wifi or Internet Connection
61 |
62 | Optional things
63 |
64 | * One or more DS18B20s for showing the inside temperature ( https://www.google.com/#q=ds18b20 )
65 | * A string of WS2818 based RGB LEDs for the AmbiLight effect. At 40ma per LED, and 30 or so
66 | LEDs you're quickly up to needing an extra 1.2A from the power supply. Size it appropriately.
67 | One option is https://learn.adafruit.com/adafruit-neopixel-uberguide/overview)
68 | * A TSOP4838 IR Receiver to flip the page display of the PiClock (https://www.google.com/search?q=tsop4838)
69 | * An IR Remote control ( I use this little guy: https://www.google.com/search?q=Mini+Universal+Infrared+IR+TV+Set+Remote+Control+Keychain )
70 | * Button or buttons connected to some GPIO pins (and a ground pin) for flipping pages like the IR remote
71 |
72 | ## What else?
73 |
74 | The Hardware guide ( https://github.com/n0bel/PiClock/blob/master/Documentation/Hardware.md )
75 | gives more details about how to wire/connect the various extras.
76 |
77 | The Install guide ( https://github.com/n0bel/PiClock/blob/master/Documentation/Install.md )
78 | steps through all the things that you need to do to a stock Raspbian image to make the PiClock work.
79 |
80 | ## Not a Pi Person?
81 |
82 | If you want to use the PiClock on your desktop (not your Pi), I've created instructinos for that
83 | https://github.com/n0bel/PiClock/blob/master/Documentation/Install-Clock-Only.md
84 |
85 |
86 | ## History
87 |
88 | It all started one Satuday afternoon when I was feeling bored. My super duper radio
89 | controlled clock ( you know those AccuRite clocks) was WRONG!. Apparently the
90 | daylight savings time adjustment was coded to the pre-2007 dates. I was going
91 | to go get something new.. when I spotted an unused monitor in the corner of my
92 | livingroom... My eyes flicked back and forth between it and the wall. I had
93 | recently been playing with a Raspberry Pi Model B, and of course the idea was born.
94 |
95 | The initial clock was built as a static web page hosted in the Pi itself and run from
96 | the Midori browser in kiosk mode. Javascript and Ajax methods were used to pull
97 | the forecast from some free weather site (don't remember) and the local NWS radar
98 | image. The Pi ran at about 60% cpu, having to move the second hand once per second
99 | while re-rendering the other hands and clock face layers.
100 |
101 | After well over a year, and some minor changes, I decided to give it a facelift,
102 | change the weather to Weather Underground and the background maps to Google Maps.
103 | Well the Midori browser really had a tough time keeping up with all that going on.
104 | You could see it skipping past seconds two at a time. And the animated radar
105 | GIFs would stall more often than not. Yes I tried Ephemeral and it was worse!
106 |
107 | I decided to rewrite the whole thing in Python. Why? I decided I needed to learn
108 | Python in more than a passing way. For some (unfathomable reason to me) Python is
109 | the language of choice for Pi's. It took a while to settle on a GUI framework.
110 | The primary issue on most of the GUIs was lack of image transparency support.
111 | Qt4 and its Python wrapper PyQt4 is what I finally chose.
112 |
113 | The details of this evolution are on my blog http://n0bel.net/v1/index.php/projects/raspberry-pi-clock
114 | as well as newer postings and updates. Some of my friends have been treated (subjected)
115 | to more timely updates via my public facebook page https://www.facebook.com/pages/Kevin-N0BEL/946361588712436
116 |
117 | And of course I tweet https://twitter.com/KevinN0BEL, Pin https://www.pinterest.com/kevinuhir/,
118 | Instagram https://instagram.com/kevin_n0bel/, and hack https://hackaday.io/n0bel
119 |
--------------------------------------------------------------------------------
/Documentation/ds18b20.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Documentation/ds18b20.jpg
--------------------------------------------------------------------------------
/Documentation/gpiobuttons.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Documentation/gpiobuttons.jpg
--------------------------------------------------------------------------------
/Documentation/tsop4838.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Documentation/tsop4838.jpg
--------------------------------------------------------------------------------
/IR/IRCodes.pl:
--------------------------------------------------------------------------------
1 | open(C,"/etc/lirc/lircd.conf");
2 |
3 | while()
4 | {
5 | if (m/(KEY_[A-Z0-9]+)\s+([0-9a-fx]+)/i)
6 | {
7 | $k{$2} = $1;
8 | }
9 | }
10 | close C;
11 | foreach (sort keys %k)
12 | {
13 | print $_." ".$k{$_}."\n";
14 | }
15 | open(X,"mode2 -d /dev/lirc0|");
16 | $ps = 0;
17 | $pp = 0;
18 | $bc = 0;
19 | while()
20 | {
21 | #print;
22 | chop;
23 | ($c, $t) = split;
24 | if ($c eq 'pulse')
25 | {
26 | if ($t > 8000) { $b = 0; $bc = 0; $ps = 0; $pp = 0; $lp = $t; next; }
27 | if ($t > 400 && $t < 700) { $pp = 1; }
28 | }
29 | if ($c eq 'space')
30 | {
31 | if ($t > 10000)
32 | {
33 | printf("*** %016x %016x %d %d\n",$b,$b^0x00ff00ff,$lp, $ls);
34 | $s = sprintf("0x%016x",$b);
35 | if (defined($k{$s}))
36 | {
37 | print "********* $k{$s}\n";
38 | }
39 | }
40 | if ($t > 4000) { $b = 0; $bc = 0; $ps = 0; $pp = 0; $ls = $t; next; }
41 | if ($t > 400 && $t < 700) { $ps = 1; }
42 | if ($t > 1400 && $t < 1800) { $ps = 2; }
43 | }
44 | if ($ps > 0 && $pp > 0)
45 | {
46 | $bc++;
47 | if ($pp == 1 && $ps == 2)
48 | {
49 | $b = $b << 1;
50 | $b = $b | 1;
51 | #print "*1* $bc\n";
52 | }
53 | if ($pp == 1 && $ps == 1)
54 | {
55 | $b = $b << 1;
56 | #print "*0* $bc\n";
57 | }
58 | $ps = 0;
59 | $pp = 0;
60 | }
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/IR/lircd.conf:
--------------------------------------------------------------------------------
1 | begin remote
2 |
3 | name KeyFobRemote
4 | bits 32
5 | flags SPACE_ENC
6 | eps 20
7 | aeps 200
8 |
9 | header 8800 4400
10 | one 550 1650
11 | zero 550 550
12 | ptrail 550
13 | repeat 8800 2200
14 | gap 38500
15 | toggle_bit 0
16 |
17 | frequency 38000
18 |
19 | begin codes
20 | KEY_F1 0x0000000008f7e817
21 | KEY_DOWN 0x0000000008f718e7
22 | KEY_UP 0x0000000008f79867
23 | KEY_RIGHT 0x0000000008f748b7
24 | KEY_LEFT 0x0000000008f7a857
25 | KEY_F2 0x0000000008f7d02f
26 | KEY_F3 0x0000000008f7906f
27 | end codes
28 |
29 | end remote
30 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Kevin Uhlir
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/Leds/NeoAmbi.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | # Must be run under sudo
3 | # Requires: sudo pip install rpi_ws281x
4 |
5 | import _rpi_ws281x as ws
6 | from time import sleep, time
7 | from math import modf
8 | import colorsys
9 |
10 | # LED configuration.
11 | LED_COUNT = 27 # How many LEDs to light.
12 |
13 | # 0..2
14 | LED_CHANNEL = 0
15 |
16 | # Frequency of the LED signal. Should be 800khz or 400khz
17 | LED_FREQ_HZ = 800000
18 |
19 |
20 | # DMA channel to use, can be 0-14.
21 | LED_DMA_NUM = 5
22 |
23 | # GPIO connected to the LED signal line. Must support PWM
24 | LED_GPIO = 18
25 |
26 | # Set to 0 for darkest and 255 for brightest
27 | LED_BRIGHTNESS = 255
28 |
29 | # Set to 1 to invert the LED signal, good if using NPN
30 | # transistor as a 3.3V->5V level converter. Keep at 0
31 | # for a normal/non-inverted signal.
32 | LED_INVERT = 0
33 |
34 |
35 | # from RGB in float 0..1.0 to NeoPixel Color 0..255
36 | def toNeoPixelColor(r, g, b):
37 | if r > 1:
38 | r = 1
39 | if g > 1:
40 | g = 1
41 | if b > 1:
42 | b = 1
43 | if r < 0:
44 | r = 0
45 | if g < 0:
46 | g = 0
47 | if b < 0:
48 | b = 0
49 | c = ((int(r * 255) & 0xff) << 16 |
50 | (int(g * 255) & 0xff) << 8 | (int(b * 255) & 0xff))
51 | return(c)
52 |
53 |
54 | leds = ws.new_ws2811_t()
55 |
56 | channel = ws.ws2811_channel_get(leds, LED_CHANNEL)
57 |
58 | ws.ws2811_channel_t_count_set(channel, LED_COUNT)
59 | ws.ws2811_channel_t_gpionum_set(channel, LED_GPIO)
60 | ws.ws2811_channel_t_invert_set(channel, LED_INVERT)
61 | ws.ws2811_channel_t_brightness_set(channel, LED_BRIGHTNESS)
62 |
63 | ws.ws2811_t_freq_set(leds, LED_FREQ_HZ)
64 | ws.ws2811_t_dmanum_set(leds, LED_DMA_NUM)
65 |
66 | resp = ws.ws2811_init(leds)
67 | if resp != 0:
68 | raise RuntimeError('ws2811_init failed with code {0}'.format(resp))
69 |
70 | try:
71 | offset = 0
72 | while True:
73 | (fractionOfMinute, dummy) = modf(time() / 60.0)
74 | for i in range(LED_COUNT):
75 | p = i / float(LED_COUNT) # 0.0..1.0 by position on string
76 | q = p + fractionOfMinute
77 | while(q > 1):
78 | q = q - 1.0 # normalize for overflow
79 | (r, g, b) = colorsys.hsv_to_rgb(q, 1.0, 1.0)
80 | ws.ws2811_led_set(channel, i, toNeoPixelColor(r, g, b))
81 |
82 | resp = ws.ws2811_render(leds)
83 | if resp != 0:
84 | raise RuntimeError('ws2811_render failed with code {0}'.
85 | format(resp))
86 |
87 | sleep(0.2)
88 |
89 | finally:
90 | for i in range(LED_COUNT):
91 | ws.ws2811_led_set(channel, i, 0)
92 | resp = ws.ws2811_render(leds)
93 | if resp != 0:
94 | raise RuntimeError('ws2811_render failed with code {0}'.format(resp))
95 | ws.ws2811_fini(leds)
96 | ws.delete_ws2811_t(leds)
97 |
--------------------------------------------------------------------------------
/PiClock.desktop:
--------------------------------------------------------------------------------
1 | [Desktop Entry]
2 | Encoding=UTF-8
3 | Type=Application
4 | Name=PiClock
5 | Comment=
6 | Exec=/bin/sh -c "/bin/sh ~/PiClock/startup.sh -m 15"
7 | StartupNotify=false
8 | Terminal=false
9 | Hidden=false
10 |
--------------------------------------------------------------------------------
/Pictures/20141222_220127.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Pictures/20141222_220127.jpg
--------------------------------------------------------------------------------
/Pictures/20141227_174953.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Pictures/20141227_174953.jpg
--------------------------------------------------------------------------------
/Pictures/2015-05-10_17-01-52.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Pictures/2015-05-10_17-01-52.png
--------------------------------------------------------------------------------
/Pictures/2015-05-16_17-36-06.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Pictures/2015-05-16_17-36-06.png
--------------------------------------------------------------------------------
/Pictures/20150307_222711.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Pictures/20150307_222711.jpg
--------------------------------------------------------------------------------
/Pictures/20150326_225245.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Pictures/20150326_225245.jpg
--------------------------------------------------------------------------------
/Pictures/20150326_225305_Fotor_Collage.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Pictures/20150326_225305_Fotor_Collage.jpg
--------------------------------------------------------------------------------
/Pictures/20150404_165441_Fotor_Collage.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Pictures/20150404_165441_Fotor_Collage.jpg
--------------------------------------------------------------------------------
/Pictures/20150412_182821a.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/Pictures/20150412_182821a.jpg
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # PiClock
2 | A Fancy Clock built around a monitor and a Raspberry Pi
3 |
4 | 
5 |
6 | This project started out as a way to waste a Saturday afternoon.
7 | I had a Raspberry Pi and an extra monitor and had just taken down an analog clock from my livingroom wall.
8 | I was contemplating getting a radio sync'ed analog clock to replace it, so I didn't have to worry about
9 | it being accurate.
10 |
11 | But instead the PiClock was born.
12 |
13 | The early days and evolution of it are chronicled on my blog http://n0bel.net/v1/index.php/projects/raspberry-pi-clock
14 |
15 | If you want to build your own, I'd suggest starting with the overview
16 | https://github.com/n0bel/PiClock/blob/master/Documentation/Overview.md
17 |
18 | If you want to use the PiClock on your desktop (not your Pi), I'd suggest using these instructions.
19 | https://github.com/n0bel/PiClock/blob/master/Documentation/Install-Clock-Only.md
20 |
21 | All of the extra hardware (IR Remote, GPIO buttons, Temperature, LEDs) are optional, so you can then jump to the install guide
22 | https://github.com/n0bel/PiClock/blob/master/Documentation/Install.md
23 |
24 | Of course you can jump to the hardware guide anytime https://github.com/n0bel/PiClock/blob/master/Documentation/Hardware.md
25 |
--------------------------------------------------------------------------------
/Temperature/TempNames.py:
--------------------------------------------------------------------------------
1 | # these are the IDs of the DS18B20's
2 | # and their corresponding names displayed on the clock
3 | sensornames = {
4 | '0000058e0f0c': 'Inside',
5 | '0000031b462b': 'Closer',
6 | '0000031b3dae': 'Farther',
7 | '0000031b54e7': 'Outside',
8 | '0000031b4f09': 'Inside2'
9 | }
10 |
--------------------------------------------------------------------------------
/Temperature/TempServer.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | # small web server that polls 18B20's that it finds
3 | # and makes them available as a json response
4 | # see TempNames.py for sensor id to name mapping
5 | #
6 | from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
7 | from w1thermsensor import W1ThermSensor
8 | import json
9 | import time
10 | import socket
11 | from threading import Thread, Lock
12 | from TempNames import sensornames
13 |
14 | temps = {}
15 | temptimes = {}
16 | lock = Lock()
17 |
18 | PORT_NUMBER = 48213
19 |
20 | # This class will handles any incoming request from
21 | # the browser
22 |
23 |
24 | class myHandler(BaseHTTPRequestHandler):
25 |
26 | def do_OPTIONS(self):
27 | self.send_response(200, "ok")
28 | self.send_header('Access-Control-Allow-Origin', '*')
29 | self.send_header('Access-Control-Allow-Methods', '*')
30 | self.send_header('Access-Control-Allow-Headers',
31 | "x-requested-with, origin, x-csrftoken," +
32 | " content-type, accept"
33 | )
34 | self.end_headers()
35 |
36 | def do_GET(self):
37 | global temps, lock
38 | self.send_response(200)
39 | self.send_header('Content-type', 'text/json')
40 | self.send_header('Access-Control-Allow-Origin', '*')
41 | self.end_headers()
42 | s = {'temp': '', 'temps': {}}
43 | lock.acquire()
44 | for k in temps:
45 | if s['temp'] == '':
46 | s['temp'] = "%.1f" % temps[k]
47 | s['temps'][sensorname(k)] = "%.1f" % temps[k]
48 | lock.release()
49 | self.wfile.write(json.dumps(s))
50 |
51 |
52 | def sensorname(str):
53 | try:
54 | return sensornames[str]
55 | except KeyError:
56 | return 'temp-' + str
57 |
58 |
59 | def t_http():
60 | try:
61 | server = HTTPServer(('0.0.0.0', PORT_NUMBER), myHandler)
62 | print 'Started httpserver on port ', PORT_NUMBER
63 | server.serve_forever()
64 | except:
65 | server.close()
66 |
67 |
68 | def t_udp():
69 | global temps, lock
70 | sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
71 | server_address = ('', 53535)
72 | sock.bind(server_address)
73 | while True:
74 | data, address = sock.recvfrom(4096)
75 | (addr, temp) = data.split(':')
76 | saddr = [addr[i:i + 2] for i in range(0, len(addr), 2)]
77 | saddr.reverse()
78 | saddr = saddr[1:7]
79 | addr = ''.join(saddr)
80 | tempf = float(temp) * 9.0 / 5.0 + 32.0
81 | lock.acquire()
82 | temps[addr] = tempf
83 | temptimes[addr] = time.time()
84 | lock.release()
85 | print 'udp>' + addr + ':' + str(tempf)
86 |
87 |
88 | def t_temp():
89 | while True:
90 | for sensor in W1ThermSensor.get_available_sensors():
91 | lock.acquire()
92 | temps[sensor.id] = sensor.get_temperature(W1ThermSensor.DEGREES_F)
93 | temptimes[sensor.id] = time.time()
94 | print 'hwr>' + sensor.id + ':' + str(temps[sensor.id])
95 | lock.release()
96 |
97 | lock.acquire()
98 | todelete = []
99 | expire = time.time() - 60 * 10
100 | for t in temptimes:
101 | if temptimes[t] < expire:
102 | todelete.append(t)
103 | for t in todelete:
104 | temptimes.pop(t, None)
105 | temps.pop(t, None)
106 | print "del>" + t
107 | lock.release()
108 |
109 | time.sleep(120)
110 |
111 | t_httpt = Thread(target=t_http)
112 | t_httpt.daemon = True
113 | t_httpt.start()
114 |
115 | t_udpt = Thread(target=t_udp)
116 | t_udpt.daemon = True
117 | t_udpt.start()
118 |
119 | t_tempt = Thread(target=t_temp)
120 | t_tempt.daemon = True
121 | t_tempt.start()
122 |
123 | try:
124 | while True:
125 | time.sleep(.1)
126 | except KeyboardInterrupt:
127 | exit()
128 |
--------------------------------------------------------------------------------
/gimp/Readme.md:
--------------------------------------------------------------------------------
1 | # Clock face and background source files
2 |
3 | These are GIMP files which are the source files for the images I've created for the PiClock.
--------------------------------------------------------------------------------
/gimp/clockbackground.xcf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/gimp/clockbackground.xcf
--------------------------------------------------------------------------------
/gimp/clockbackground5.xcf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/gimp/clockbackground5.xcf
--------------------------------------------------------------------------------
/gimp/clockface3.xcf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/gimp/clockface3.xcf
--------------------------------------------------------------------------------
/gimp/hourhand.xcf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/gimp/hourhand.xcf
--------------------------------------------------------------------------------
/gimp/jeansxcf.xcf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/gimp/jeansxcf.xcf
--------------------------------------------------------------------------------
/gimp/minhand.xcf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/gimp/minhand.xcf
--------------------------------------------------------------------------------
/gimp/sechand.xcf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/gimp/sechand.xcf
--------------------------------------------------------------------------------
/gimp/squares2.xcf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/gimp/squares2.xcf
--------------------------------------------------------------------------------
/gimp/squres1.xcf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/n0bel/PiClock/e18e5b1a9241035d905f143a6026a33bc21e362e/gimp/squres1.xcf
--------------------------------------------------------------------------------
/startup.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # Startup script for the PiClock
3 | #
4 | # Designed to be started from PiClock.desktop (autostart)
5 | #
6 | # or alternatively from crontab as follows
7 | #@reboot sh /home/pi/PiClock/startup.sh
8 |
9 | #
10 | cd $HOME/PiClock
11 |
12 | #
13 | if [ "$DISPLAY" = "" ]
14 | then
15 | export DISPLAY=:0
16 | fi
17 |
18 | # wait for Xwindows and the desktop to start up
19 | MSG="echo Waiting 45 seconds before starting"
20 | DELAY="sleep 45"
21 | if [ "$1" = "-n" -o "$1" = "--no-sleep" -o "$1" = "--no-delay" ]
22 | then
23 | MSG=""
24 | DELAY=""
25 | shift
26 | fi
27 | if [ "$1" = "-d" -o "$1" = "--delay" ]
28 | then
29 | MSG="echo Waiting $2 seconds before starting"
30 | DELAY="sleep $2"
31 | shift
32 | shift
33 | fi
34 | if [ "$1" = "-m" -o "$1" = "--message-delay" ]
35 | then
36 | MSG="echo Waiting $2 seconds for response before starting"
37 | #DELAY="xmessage -buttons Now:0,Cancel:1 -default Now -timeout $2 Starting PiClock in $2 seconds"
38 | DELAY='zenity --question --title PiClock --ok-label=Now --cancel-label=Cancel --timeout '$2' --text "Starting PiClock in '$2' seconds" >/dev/null 2>&1'
39 | shift
40 | shift
41 | fi
42 |
43 | $MSG
44 | eval $DELAY
45 | if [ $? -eq 1 ]
46 | then
47 |
48 | echo "PiClock Cancelled"
49 | exit 0
50 | fi
51 |
52 | #xmessage -timeout 5 Starting PiClock....... &
53 | zenity --info --timeout 3 --text "Starting PiClock......." >/dev/null 2>&1 &
54 |
55 | # stop screen blanking
56 | echo "Disabling screen blanking...."
57 | xset s off
58 | xset -dpms
59 | xset s noblank
60 |
61 | # get rid of mouse cursor
62 | pgrep unclutter >/dev/null 2>&1
63 | if [ $? -eq 1 ]
64 | then
65 | unclutter >/dev/null 2>&1 &
66 | fi
67 |
68 | echo "Setting sound to max (assuming Monitor Tv controls volume)...."
69 | # push sound level to maximum
70 | amixer cset numid=1 -- 400 >/dev/null 2>&1
71 |
72 | # NeoPixel AmbiLights
73 | echo "Checking for NeoPixels Ambilight..."
74 | cd Leds
75 | python -c "import rpi_ws281x" >/dev/null 2>&1
76 | if [ $? -eq 0 ]
77 | then
78 | pgrep -f NeoAmbi.py
79 | if [ $? -eq 1 ]
80 | then
81 | echo "Starting NeoPixel Ambilight Service..."
82 | sudo python NeoAmbi.py &
83 | fi
84 | fi
85 | cd ..
86 |
87 | echo "Checking for GPIO Buttons..."
88 | # gpio button to keyboard input
89 | if [ -x Button/gpio-keys ]
90 | then
91 | pgrep -f gpio-keys
92 | if [ $? -eq 1 ]
93 | then
94 | echo "Starting gpio-keys Service..."
95 | sudo Button/gpio-keys 23:KEY_SPACE 24:KEY_F2 25:KEY_UP &
96 | fi
97 | fi
98 |
99 | echo "Checking for Temperature Sensors..."
100 | # for temperature sensor(s) on One Wire bus
101 | python -c "import w1thermsensor" >/dev/null 2>&1
102 | if [ $? -eq 0 ]
103 | then
104 | pgrep -f TempServer.py
105 | if [ $? -eq 1 ]
106 | then
107 | echo "Starting Temperature Service..."
108 | cd Temperature
109 | python TempServer.py &
110 | cd ..
111 | fi
112 | fi
113 |
114 | # the main app
115 | cd Clock
116 | if [ "$1" = "-s" -o "$1" = "--screen-log" ]
117 | then
118 | echo "Starting PiClock.... logging to screen."
119 | python -u PyQtPiClock.py
120 | else
121 | # create a new log file name, max of 7 log files
122 | echo "Rotating log files...."
123 | rm PyQtPiClock.7.log >/dev/null 2>&1
124 | mv PyQtPiClock.6.log PyQtPiClock.7.log >/dev/null 2>&1
125 | mv PyQtPiClock.5.log PyQtPiClock.6.log >/dev/null 2>&1
126 | mv PyQtPiClock.4.log PyQtPiClock.5.log >/dev/null 2>&1
127 | mv PyQtPiClock.3.log PyQtPiClock.4.log >/dev/null 2>&1
128 | mv PyQtPiClock.2.log PyQtPiClock.3.log >/dev/null 2>&1
129 | mv PyQtPiClock.1.log PyQtPiClock.2.log >/dev/null 2>&1
130 | echo "Starting PiClock.... logging to Clock/PyQtPiClock.1.log "
131 | python -u PyQtPiClock.py >PyQtPiClock.1.log 2>&1
132 | fi
133 |
--------------------------------------------------------------------------------
/switcher.sh:
--------------------------------------------------------------------------------
1 | cd $HOME/PiClock
2 | pkill -INT -f PyQtPiClock.py
3 | cd Clock
4 | if [ "$DISPLAY" = "" ]
5 | then
6 | export DISPLAY=:0
7 | fi
8 | # the main app
9 | # create a new log file name, max of 7 log files
10 | echo "Rotating log files...."
11 | rm PyQtPiClock.7.log >/dev/null 2>&1
12 | mv PyQtPiClock.6.log PyQtPiClock.7.log >/dev/null 2>&1
13 | mv PyQtPiClock.5.log PyQtPiClock.6.log >/dev/null 2>&1
14 | mv PyQtPiClock.4.log PyQtPiClock.5.log >/dev/null 2>&1
15 | mv PyQtPiClock.3.log PyQtPiClock.4.log >/dev/null 2>&1
16 | mv PyQtPiClock.2.log PyQtPiClock.3.log >/dev/null 2>&1
17 | mv PyQtPiClock.1.log PyQtPiClock.2.log >/dev/null 2>&1
18 | # start the clock
19 | echo "Starting PiClock...."
20 | python -u PyQtPiClock.py $1 >PyQtPiClock.1.log 2>&1 &
21 |
--------------------------------------------------------------------------------
/update.py:
--------------------------------------------------------------------------------
1 | import sys
2 | import os.path
3 | import os
4 | import re
5 |
6 | print "Updating Python Modules"
7 | print "Updating python-dateutil"
8 | os.system("sudo pip install python-dateutil --upgrade")
9 | print "Updating tzlocal"
10 | os.system("sudo pip install tzlocal --upgrade")
11 | print "Updating python-metar"
12 | os.system("sudo pip install python-metar --upgrade")
13 |
14 | buttonFileName = 'Button/gpio-keys'
15 | print "Checking " + buttonFileName
16 | if os.path.isfile(buttonFileName):
17 | try:
18 | print "Setting proper permissions on " + buttonFileName
19 | os.chmod(buttonFileName, 0744)
20 | except:
21 | pass
22 |
23 | apikeysFileName = 'Clock/ApiKeys.py'
24 | wuapi_re = re.compile('\\s*wuapi\\s*=')
25 | dsapi_re = re.compile('\\s*dsapi\\s*=')
26 | ccapi_re = re.compile('\\s*ccapi\\s*=')
27 | owmapi_re = re.compile('\\s*owmapi\\s*=')
28 |
29 | print "Checking " + apikeysFileName
30 | if (os.path.isfile(apikeysFileName)):
31 | altered = False
32 | foundcc = False
33 | foundowm = False
34 | newfile = ''
35 | apikeys = open(apikeysFileName, "r")
36 | for aline in apikeys:
37 | if ccapi_re.match(aline):
38 | foundcc = True
39 | if owmapi_re.match(aline):
40 | foundwom = True
41 | if wuapi_re.match(aline):
42 | print "Removing wuapi key from " + apikeysFileName
43 | altered = True
44 | if dsapi_re.match(aline):
45 | print "Removing dsapi key from " + apikeysFileName
46 | altered = True
47 | else:
48 | newfile += aline
49 | apikeys.close()
50 |
51 | if not foundcc and not foundowm:
52 | print "This version of PiClock requires a openweathermap api key."
53 | print "https://openweathermap.org/price use the Free option"
54 | print "Enter your openweathermap api key."
55 | print "key:",
56 | k = sys.stdin.readline()
57 | k = k.strip()
58 | if len(k) > 1:
59 | newfile += "owmapi = '" + k + "'"
60 | altered = True
61 |
62 | if altered:
63 | print "Writing Updated " + apikeysFileName
64 | apikeys = open(apikeysFileName, "w")
65 | apikeys.write(newfile)
66 | apikeys.close()
67 | else:
68 | print "No changes made to " + apikeysFileName
69 |
70 | try:
71 | from rpi_ws281x import * # NOQA
72 | except:
73 | print "NeoAmbi.py now uses rpi-ws281x/rpi-ws281x-python"
74 | print "Please install it as follows:"
75 | print "sudo pip install rpi_ws281x"
76 |
--------------------------------------------------------------------------------