-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathmymodule.py
249 lines (188 loc) · 9.92 KB
/
mymodule.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
#!/usr/bin/python3
# -*- coding: utf-8 -*-
"""
Third party module template (inkycal-compatible module) for release 2.0.0
Copyright by aceisace
"""
#############################################################################
# Required imports (do not remove)
#############################################################################
# Required for setting up this module
from inkycal.modules.template import inkycal_module
from inkycal.custom import *
#############################################################################
# Built-in library imports (change as desired)
#############################################################################
# Built-in libraries go here
from random import shuffle
#############################################################################
# External library imports (always use try-except)
#############################################################################
# For external libraries, which require installing,
# use try...except ImportError to check if it has been installed
# If it is not found, print a short message on how to install this dependency
try:
import feedparser
except ImportError:
print('feedparser is not installed! Please install with:')
print('pip3 install feedparser')
#############################################################################
# Filename + logging (do not remove)
#############################################################################
# Get the name of this file, set up logging for this filename
filename = os.path.basename(__file__).split('.py')[0]
logger = logging.getLogger(filename)
#############################################################################
# Class setup
#############################################################################
# Change 'Simple' to a different name, the first letter must be a Capital!
# Avoid naming the class with too long names
class Simple(inkycal_module):
""" Simple Class
Once sentence describing what this module does,
e.g. Display hello world with your name!
"""
# name is the name that will be shown on the web-ui
# may be same or different to the class name (Do not remove this)
name = "Simple - say hello world"
# create a dictionary containing variables which your module must have
# to run correctly, e.g. if your module needs an 'api-key' and a 'name':
requires = {
# A simple text input; users can choose what to enter by keyboard
'api_key': {"label" : "Please enter your api-key from some-website"},
# A simple text input; users can choose what to enter by keyboard
'username': {"label": "Please enter a username"},
}
# The format for the above is: |"key_name": {"Desription what this means"},|
# create a dictionary containing variables which your module optionally
# can have to run correctly, e.g. if your module needs has optional
# parameters like: 'api-key' and a 'name':
#########################################################################
optional = {
# A simple text input with multiple values separated by a comma
'hobbies': {"label": "What is/are your hobbies? Separate multiple ones "
"with a comma"},
# A simple text input which should be a number
'age': {"label": "What is your age? Please enter a number"},
# A dropdown list variable. This will allow users to select something
# from the list in options. Instead of True/False, you can have
# strings, numbers and other datatypes. Add as many options as you need
'likes_inkycal': {
"label": "Do you like Inkycal?",
"options": [True, False],
},
# A dropdown list with a fallback value in case the user didn't select
# anything
'show_smiley': {
"label": "Show a smiley next to your name?",
"options": [True, False],
"default": True,
},
}
########################################################################
# Initialise the class (do not remove)
def __init__(self, config):
"""Initialize your module module"""
# Initialise this module via the inkycal_module template (required)
super().__init__(config)
config = config['config']
# Check if all required parameters are present
# remove this if your module has no required parameters
for param in self.requires:
if not param in config:
raise Exception('config is missing {}'.format(param))
# the web-UI removes any blank space from the input
# It can only output strings or booleans, integers and lists need to be
# converted manually, e.g.
# if you need a boolean (True/False), no conversion is needed:
self.show_smiley = config['show_smiley']
# if you need a single word input, like the api-ley, no conversion is needed
self.api_key = config['api_key']
# if you need a integer (number) input, you have to convert this to a int
#-----------------------------------------------------------------------#
# bad example :/
self.age = int( config["age"] )
# Remember age was a optional parameter? What if no age was entered
# and there is no fallback value? Then the age would be None.
# This would cause crashing right here
# good example :)
if config["age"] and isinstance(config["age"], str):
self.age = int( config["age"] )
else:
self.age = 10 # just a joke, no offense
# -> Check if age was entered and if it's a string (entered via web-UI)
# If something was entered for age, convert it to a number
# The else statement is executed when nothing was entered for age
# You could assign a custom value now or print something.
#-----------------------------------------------------------------------#
# if you need a list of words, you have to convert the string to a list
#-----------------------------------------------------------------------#
# good example :)
if config["hobbies"] and isinstance(config["hobbies"], str):
self.hobbies = config["age"].split(",")
# split splits the string on each comma -> gives a list
# even if a single value was entered, it will be converted to a list
else:
self.hobbies = [] # empty list if nothing was entered by user
#-----------------------------------------------------------------------#
# give an OK message
print(f'{filename} loaded')
#############################################################################
# Validation of module specific parameters (optional) #
#############################################################################
def _validate(self):
"""Validate module-specific parameters"""
# Check the type of module-specific parameters
# This function is optional, but useful for debugging.
# Here, we are checking if do_something (from init) is True/False
if not isinstance(self.age, int):
print(f"age has to be a number, but given value is {self.age}")
#############################################################################
# Generating the image #
#############################################################################
def generate_image(self):
"""Generate image for this module"""
# Define new image size with respect to padding
im_width = int(self.width - (2 * self.padding_left))
im_height = int(self.height - (2 * self.padding_top))
im_size = im_width, im_height
logger.info('image size: {} x {} px'.format(im_width, im_height))
# Use logger.info(), logger.debug(), logger.warning() to display
# useful information for the developer
logger.info('image size: {} x {} px'.format(im_width, im_height))
# Create an image for black pixels and one for coloured pixels (required)
im_black = Image.new('RGB', size = im_size, color = 'white')
im_colour = Image.new('RGB', size = im_size, color = 'white')
#################################################################
# Your code goes here #
# Write/Draw something on the image
# You can use these custom functions to help you create the image:
# - write() -> write text on the image
# - get_fonts() -> see which fonts are available
# - get_system_tz() -> Get the system's current timezone
# - auto_fontsize() -> Scale the fontsize to the provided height
# - textwrap() -> Split a paragraph into smaller lines
# - internet_available() -> Check if internet is available
# - draw_border() -> Draw a border around the specified area
# If these aren't enough, take a look at python Pillow (imaging library)'s
# documentation.
#################################################################
# return the images ready for the display
return im_black, im_colour
if __name__ == '__main__':
print('running {0} in standalone mode'.format(filename))
################################################################################
# Last steps
# Wow, you made your own module for the inkycal project! Amazing :D
# To make sure this module can be used with inkycal, you need to register it with inkycal
# If not there already, copy your module to Inkycal/inkycal/modules
# Copy the full path of your module (e.g. right click->copy path), it should look like: /home/pi/Inkycal/inkycal/modules/mymodule.py or similar
# then open a python console and run:
# import Inkycal
# Inkycal.add_module('full/path/to/your/new/module.py')
# To remove your module, run the following in a python console:
# import Inkycal
# Inkycal.remove_module('filename.py') # Only the filename, e.g. 'mymodule.py' is required.
# How do I now import my module?
# from inkycal.modules import Class
# Where Class is the name of the class inside your module (e.g. Simple)