Skip to content

Commit

Permalink
Fix sunrise/sunset calculation, update manual
Browse files Browse the repository at this point in the history
  • Loading branch information
kizniche committed Jul 27, 2019
1 parent 4ba8dac commit a362027
Show file tree
Hide file tree
Showing 9 changed files with 296 additions and 257 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ This release changes how user-created Python code is executed. This affects Pyth
2. Python Code Inputs
* Use 4-space indentation (not 2-space, tab, or other)

### Bugfixes

- Fix sunrise/sunset calculation

### Features

Expand Down
128 changes: 70 additions & 58 deletions mycodo-manual.html

Large diffs are not rendered by default.

Binary file modified mycodo-manual.pdf
Binary file not shown.
157 changes: 86 additions & 71 deletions mycodo-manual.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1422,20 +1422,25 @@ measurement or GPIO state.
Conditional Setup Guide

Python 3 is the environment that these conditionals will be executed.
The following
The following functions can be used within your code.

------------------------------------------------------------------------
Function Description
----------------------- ------------------------------------------------
measure(“{ID}”) Returns a measurement for the Condition with ID.
Note: Indentation must use 4 spaces (not 2 spaces, tabs, or other).

measure_dict(“{ID}”) Returns a dictionary of measurement for the
Condition with ID.
---------------------------------------------------------------------------
Function Description
-------------------------- ------------------------------------------------
self.measure(“{ID}”) Returns a measurement for the Condition with ID.

run_action(“{ID}”) Executes the Action with ID.
self.measure_dict(“{ID}”) Returns a dictionary of measurement for the
Condition with ID.

run_all_actions() Executes all actions.
------------------------------------------------------------------------
self.run_action(“{ID}”) Executes the Action with ID.

self.run_all_actions() Executes all actions.

self.logger.info() Writes a log line to the daemon log. ‘info’ may
also be changed to ‘error’ or ‘debug’.
---------------------------------------------------------------------------

Since the Python code contained in the Conditional Statement must be
formatted properly, it’s best to familiarize yourself with the basics of
Expand All @@ -1448,10 +1453,10 @@ Conditional. Read all of this section, including the examples, below, to
fully understand how to configure a conditional properly.

IMPORTANT: If a measurement hasn’t been acquired within the Max Age that
is set, “None” will be returned when measure(“{ID}”) is called in the
code. It is very important that you account for this. All examples below
incorporate a test for the measurement being None, and this should not
be removed. If an error occurs (such as if the statement resolves to
is set, “None” will be returned when self.measure(“{ID}”) is called in
the code. It is very important that you account for this. All examples
below incorporate a test for the measurement being None, and this should
not be removed. If an error occurs (such as if the statement resolves to
comparing None to a numerical value, such as “if None < 23”), then the
code will stop there and an error will be logged in the daemon log.
Accounting for None is useful for determining if an Input is no longer
Expand All @@ -1471,9 +1476,9 @@ the screenshots, below, that correspond to the numbers in parentheses:
(underlined).
- The default Conditional Statement (3) contains placeholder IDs that
need to be changed to your Condition and Action IDs. Change the ID
in measure(“{asdf1234}”) to your Condition ID. Change the ID in
run_action(“{qwer5678}”, message=message) to your Action ID. Click
Save at the top of the Conditional.
in self.measure(“{asdf1234}”) to your Condition ID. Change the ID in
self.run_action(“{qwer5678}”, message=message) to your Action ID.
Click Save at the top of the Conditional.
- The logic used in the Conditional Statement will need to be adjusted
to suit your particular needs. Additionally, you may add more
Conditions or Actions. See the
Expand All @@ -1495,47 +1500,47 @@ manual to understand how to use Conditionals.

Simple Conditional Statement examples:

Each measure(“{ID}”) will return the most recent measurement obtained
from that particular measurement under the Conditions section of the
Conditional, as long as it’s within the set Max Age.
Each self.measure(“{ID}”) will return the most recent measurement
obtained from that particular measurement under the Conditions section
of the Conditional, as long as it’s within the set Max Age.

# Example 1, no measurement, useful to notify by email when an Input stops working
if measure("{asdf1234}") is None:
run_all_actions()
if self.measure("{asdf1234}") is None:
self.run_all_actions()

# Example 2, test two measurements
measure_1 = measure("{asdf1234}")
measure_2 = measure("{hjkl5678}")
measure_1 = self.measure("{asdf1234}")
measure_2 = self.measure("{hjkl5678}")
if None not in [measure_1, measure_2]:
if measure_1 < 20 and measure_2 > 10:
run_all_actions()
self.run_all_actions()

# Example 3, test two measurements and sum of measurements
measure_1 = measure("{asdf1234}")
measure_2 = measure("{hjkl5678}")
measure_1 = self.measure("{asdf1234}")
measure_2 = self.measure("{hjkl5678}")
if None not in [measure_1, measure_2]:
sum = measure_1 + measure_2
if measure_1 > 2 and 10 < measure_2 < 23 and sum < 30.5:
run_all_actions()
self.run_all_actions()

# Example 4, combine into one conditional
measurement = measure("{asdf1234}")
measurement = self.measure("{asdf1234}")
if measurement != None and 20 < measurement < 30:
run_all_actions()
self.run_all_actions()

# Example 5, test two measurements and convert Edge Input from 0 or 1 to True or False
measure_1 = measure("{asdf1234}")
measure_2 = measure("{hjkl5678}")
measure_1 = self.measure("{asdf1234}")
measure_2 = self.measure("{hjkl5678}")
if None not in [measure_1, measure_2]:
if bool(measure_1) and measure_2 > 10:
run_all_actions()
self.run_all_actions()

# Example 6, test measurement with "or" and a rounded measurement
measure_1 = measure("{asdf1234}")
measure_2 = measure("{hjkl5678}")
measure_1 = self.measure("{asdf1234}")
measure_2 = self.measure("{hjkl5678}")
if None not in [measure_1, measure_2]:
if measure_1 > 20 or int(round(measure_2)) in [20, 21, 22]:
run_all_actions()
self.run_all_actions()

“Measurement (Multiple)” is useful if you need to check if a particular
value has been stored in any of the past measurements (within the set
Expand All @@ -1549,11 +1554,11 @@ each_measure[‘time’] may also be used to retrieve the timestamp for the
particular measurement.

# Example 1, find a particular measurement in the past 30 minutes (set Max Age to 1800 seconds)
measurements = measure_dict("{asdf1234}")
measurements = self.measure_dict("{asdf1234}")
if measurements:
for each_measure in measurements:
if each_measure['value'] == 119:
run_all_actions()
self.run_all_actions()
break

Advanced Conditional Statement examples:
Expand All @@ -1562,77 +1567,87 @@ These examples expand on the simple examples, above, by activating
specific actions. The following examples will reference actions with IDs
that can be found under the Actions section of the Conditional. Two
example action ID will be used: “qwer1234” and “uiop5678”. Additionally,
run_all_actions() is used here, which will run all actions in the order
in which they appear in the Actions section of the Conditional.
self.run_all_actions() is used here, which will run all actions in the
order in which they appear in the Actions section of the Conditional.

# Example 1
measurement = measure("{asdf1234}")
measurement = self.measure("{asdf1234}")
if measurement is None:
run_action("{qwer1234}")
self.run_action("{qwer1234}")
elif measurement > 23:
run_action("{uiop5678}")
self.run_action("{uiop5678}")
else:
run_all_actions()
self.run_all_actions()

# Example 2, test two measurements
measure_1 = measure("{asdf1234}")
measure_2 = measure("{hjkl5678}")
measure_1 = self.measure("{asdf1234}")
measure_2 = self.measure("{hjkl5678}")
if None not in [measure_1, measure_2]:
if measure_1 < 20 and measure_2 > 10:
run_action("{qwer1234}")
run_action("{uiop5678}")
self.run_action("{qwer1234}")
self.run_action("{uiop5678}")

# Example 3, test two measurements and sum of measurements
measure_1 = measure("{asdf1234}")
measure_2 = measure("{hjkl5678}")
measure_1 = self.measure("{asdf1234}")
measure_2 = self.measure("{hjkl5678}")
if None not in [measure_1, measure_2]:
sum = measure_1 + measure_2
if measure_1 > 2 and 10 < measure_2 < 23 and sum < 30.5:
run_action("{qwer1234}")
self.run_action("{qwer1234}")
else:
run_action("{uiop5678}")
self.run_action("{uiop5678}")

# Example 4, combine into one conditional
measurement = measure("{asdf1234}")
measurement = self.measure("{asdf1234}")
if measurement != None and 20 < measurement < 30:
run_action("{uiop5678}")
self.run_action("{uiop5678}")

# Example 5, test two measurements and convert Edge Input from 0 or 1 to True or False
measure_1 = measure("{asdf1234}")
measure_2 = measure("{hjkl5678}")
measure_1 = self.measure("{asdf1234}")
measure_2 = self.measure("{hjkl5678}")
if None not in [measure_1, measure_2]:
if bool(measure_1) and measure_2 > 10:
run_all_actions()
self.run_all_actions()

# Example 6, test measurement with "or" and a rounded measurement
measure_1 = measure("{asdf1234}")
measure_2 = measure("{hjkl5678}")
measure_1 = self.measure("{asdf1234}")
measure_2 = self.measure("{hjkl5678}")
if None not in [measure_1, measure_2]:
if measure_1 > 20 or int(round(measure_2)) in [20, 21, 22]:
run_action("{qwer1234}")
self.run_action("{qwer1234}")
if measure_1 > 30:
run_action("{uiop5678}")
self.run_action("{uiop5678}")

If your action is a type that receives a message (E-Mail or Note), you
can modify this message to include extra information before it is added
to the Note or E-Mail. To do this, append a string to the variable
message and add this to the message parameter of run_action() or
run_all_actions(). Below are some examples. Note the use of “+=” instead
of “=”, which appends the string to the variable message.
self.message and add this to the message parameter of self.run_action()
or self.run_all_actions(). Below are some examples. Note the use of “+=”
instead of “=”, which appends the string to the variable self.message.

# Example 1
measurement = measure("{asdf1234}")
measurement = self.measure("{asdf1234}")
if measurement is None and measurement > 23:
message += "Measurement was {}".format(measurement)
run_action("{uiop5678}", message=message)
self.message += "Measurement was {}".format(measurement)
self.run_action("{uiop5678}", message=self.message)

# Example 2
measure_1 = measure("{asdf1234}")
measure_2 = measure("{hjkl5678}")
measure_1 = self.measure("{asdf1234}")
measure_2 = self.measure("{hjkl5678}")
if None not in [measure_1, measure_2]:
if measure_1 < 20 and measure_2 > 10:
message += "Measurement 1: {m1}, Measurement 2: {m2}".format(m1=measure_1, m2=measure_2)
run_all_actions(message=message)
self.message += "Measurement 1: {m1}, Measurement 2: {m2}".format(m1=measure_1, m2=measure_2)
self.run_all_actions(message=self.message)

Logging can also be used to log messages to the daemon log using
self.logger:

# Example 1
measurement = self.measure("{asdf1234}")
if measurement is None and measurement > 23:
self.logging.error("Warning, measurement was {}".format(measurement))
self.message += "Measurement was {}".format(measurement)
self.run_action("{uiop5678}", message=self.message)

Before activating any conditionals, it’s advised to thoroughly explore
all possible scenarios and plan a configuration that eliminates
Expand Down
Loading

0 comments on commit a362027

Please sign in to comment.