-
-
Save PaulskPt/86551032942e760910b0fb7fa6e2a1bb to your computer and use it in GitHub Desktop.
There are 2 examples of code.py in this DataToGoogle_MAGTAG Gist: | |
1) The CircuitPython script, "code_using_aio.py" (rename it to "code.py"), uses the following CircuitPython (V9) library files: | |
- adafruit_bitmap_font; | |
- adafruit_io; | |
- adafruit_magtag; | |
- adafruit_minimqtt; | |
- adafruit_ahtx0.mpy; | |
- simpleio.mpy. | |
2) The CircuitPython script, "code_using_adafruit_ntp.py" (rename it to "code.py"). | |
For this script, beside the modules used in example 1), we need also the modules: | |
socketpool; | |
adafruit_ntp; | |
and my own module: dst_prt (see below in this Gist). | |
# SPDX-FileCopyrightText: 2020 Brent Rubell, written for Adafruit Industries | |
# | |
# SPDX-License-Identifier: Unlicense | |
# | |
# File very modified by @PaulskPt. Latest updates on: 2022-08-11, 2024-03-23 | |
# (Github @PaulskPt) | |
# Last CircuitPython update on: 2024-03-22. Updated CPY to V9.0.0 | |
# This script has functionality to "hotplug-ing" the sensor. | |
# 2024-03-24 15h00 in function send_to_pushingbox() added variable stat_result. If stat == 200, stat_result | |
# will show the text "OK" in the top right of the MAGTAG page "latest sensor data". If stat != 200, stat_result | |
# will show the text "NO" (meaning: fail). | |
# 2024-03-25 13h20 added global variables use_sound and use_leds | |
# Button A will toggle sound | |
# Button B will toggle LEDs | |
# Button C will toggle the global variable wait_for_zero_sec. Then tries to write this setting to file: settings.toml. | |
# Button D will toggle the global variable my_debug. Then tries to write this setting to file: settings.toml. | |
# Note that file settings.toml can only be updated from within this script when the MAGTAG is not connected to USB. | |
# In function send_to_pushingbox() the response is 200 (OK), the LEDs will blink green if use_leds is True. | |
# the leds will blink red if the response is other than 200. | |
# For module cptoml see: https://github.com/beryllium-org/cptoml | |
# When reading the sensor the LEDs of the MAGTAG will blink one time in color Yellow. | |
# Depending on the global variable use_sound, a tone will be produced or not. | |
# When the datetime stamp and sensor data successfully are sent to Pushingbox.com, the LEDs of the MAGTAG will blink | |
# Depending on the global variable use_sound, a tone will be produced or not. | |
# one time Green. | |
# Added function is_usb() that ckecks if the board is connected to USB or not. | |
# Update 2024-03-31 | |
# Added modules: adafruit_ntp, socketpool and own module dst_prt | |
# Deleted function get_time_fm_aio() by set_INT_RTC() which uses adafruit_ntp. | |
# From file settings.toml removed "ADAFRUIT_IO_USERNAME" and "ADAFRUIT_IO_KEY" | |
""" | |
The Adafruit MAGTAG contains an ESP32-S2 WROVER chip. | |
Note: On 2022-08-10 at 17h12 utc+1 the Google Apps Script system reported that the project | |
'DataToGoogle_MAGTAG', deployment version 6, executed successfully. | |
This execution came from Pushingbox.com that was triggered by this CircuitPython script (see function 'send_data_to_google()') | |
Note also that the Google Apps Script deployment was set that it was available to 'anyone' (with the link). | |
On 2024-03-24, in Google Apps Scripts I had to create a new deployment (version 7). It executed successfully. | |
""" | |
import sys | |
import os | |
import gc | |
import supervisor | |
import board | |
import time | |
import wifi | |
import rtc | |
import ipaddress | |
from adafruit_magtag.magtag import MagTag | |
import adafruit_ahtx0 | |
import socketpool | |
import adafruit_ntp | |
from dst_PRT import dst | |
# Global flags (see setup()): | |
use_sound = None | |
use_leds = None | |
wait_for_zero_sec = None | |
my_debug = None | |
on_usb = None | |
SOUND_IDX = 0 | |
LEDS_IDX = 1 | |
ZEROSEC_IDX = 2 | |
DEBUG_IDX = 3 | |
TZ_OFFSET = None | |
sensor = None | |
stat_result = None | |
interval = None | |
ip = 0 | |
i2c = board.STEMMA_I2C() | |
try: | |
sensor = adafruit_ahtx0.AHTx0(i2c) | |
except ValueError as e: | |
print(f"Global. Error: {e}. Check wiring!") | |
pass | |
# Create an instance of the MagTag class | |
magtag = MagTag() | |
height = magtag.graphics.display.height -1 | |
width = magtag.graphics.display.width -1 | |
# Less brillance than originally (mod by @paulsk) | |
b1=25 # originally 255 | |
b2=15 # idem 150 | |
b3=18 # idem 180 | |
red_tpl = (b2, 0, 0) | |
ylw_tpl = (b1, b2, 0) | |
grn_tpl = (0, b2, 0) | |
blu_tpl = (0, 0, b2) | |
blk_tpl = (0,0,0) | |
RED = 0 | |
YLW = 1 | |
GRN = 2 | |
BLU = 3 | |
BLK = 4 | |
clr_dict = { | |
RED : "RED", | |
YLW : "YLW", | |
GRN : "GRN", | |
BLU : "BLU", | |
BLK : "BLK" | |
} | |
button_colors = (red_tpl, ylw_tpl, grn_tpl, blu_tpl, blk_tpl) # last tuple added for color black | |
button_tones = (1047, 1318, 1568, 2093, 440) | |
msg_sent = 0 | |
tmp_old = 0.00 | |
hum_old = 0.00 | |
upd_dt_old = "" | |
dts = "" # Set by get_time_fm_aio() and used in get_th_direct() | |
curr_tm = None # struct_time | |
rtc_set = False | |
rtc_bi = rtc.RTC() # create an instance of the built-in RTC | |
weekdays = {0:"Monday", 1:"Tuesday",2:"Wednesday",3:"Thursday",4:"Friday",5:"Saturday",6:"Sunday"} | |
tmp_cl = None | |
hum_cl = None | |
tm_wday = 6 | |
tm_yday = 7 | |
tm_isdst = 8 | |
rtc_DOW = DOW = { | |
0: "Monday", | |
1: "Tuesday", | |
2: "Wednesday", | |
3: "Thursday", | |
4: "Friday", | |
5: "Saturday", | |
6: "Sunday", | |
} | |
SYS_dt = None | |
set_SYS_RTC = True | |
SYS_RTC_is_set = False | |
TZ_OFFSET = int(os.getenv("TZ_OFFSET")) | |
if my_debug: | |
print(f"TZ_OFFSET= {TZ_OFFSET}") | |
pool = socketpool.SocketPool(wifi.radio) | |
ntp = adafruit_ntp.NTP(pool, tz_offset=TZ_OFFSET) | |
NTP_dt = None | |
NTP_dt_is_set = False | |
COUNTRY = None | |
STATE = None | |
dst_offset = 0 # PT wintertime | |
class Date: | |
def __init__(self): | |
self.d1 = 0 # d | |
self.m1 = 0 # m | |
self.y1 = 0 # y | |
self.d2 = 0 # d | |
self.m2 = 0 # m | |
self.y2 = 0 # y | |
self.monthDays = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] | |
# To store number of days in all months from | |
# January to Dec. | |
# This function counts number of leap years | |
# before the given date | |
# d = (dd, mo, yy) | |
def countLeapYears(self, d): | |
years = d[2] | |
# Check if the current year needs to be considered | |
# for the count of leap years or not | |
if (d[1] <= 2): | |
years -= 1 | |
# An year is a leap year if it is a multiple of 4, | |
# multiple of 400 and not a multiple of 100. | |
return int(years / 4) - int(years / 100) + int(years / 400) | |
# This function returns number of days between two | |
# given dates | |
def getDifference(self, dt1, dt2): | |
TAG = "Date.getDifference(): " | |
# COUNT TOTAL NUMBER OF DAYS BEFORE FIRST DATE 'dt1' | |
for _ in range(2): | |
if _ == 0: | |
p = dt1 | |
elif _ == 1: | |
p = dt2 | |
if not isinstance(p, tuple): | |
print(TAG+f"Parameter {"dt1" if _ == 0 else "dt2" if _ == 1 else "?"} has to be of type tuple, received type: {type(p)}") | |
self.d1 = dt1[0] | |
self.m1 = dt1[1] | |
self.y1 = dt1[2] | |
self.d2 = dt2[0] | |
self.m2 = dt2[1] | |
self.y2 = dt2[2] | |
# initialize count using years and day | |
n1 = self.y1 * 365 + self.d1 | |
# Add days for months in given date | |
for i in range(0, self.m1 - 1): | |
n1 += self.monthDays[i] | |
# Since every leap year is of 366 days, | |
# Add a day for every leap year | |
n1 += self.countLeapYears(dt1) | |
# SIMILARLY, COUNT TOTAL NUMBER OF DAYS BEFORE 'dt2' | |
n2 = self.y2 * 365 + self.d2 | |
for i in range(0, self.m2 - 1): | |
n2 += self.monthDays[i] | |
n2 += self.countLeapYears(dt2) | |
# return difference between two counts | |
return (n2 - n1) | |
class sensor_tmp: | |
def __init__(self, tmp, dt): | |
self._tmp = tmp | |
self._dt = dt | |
@property | |
def tmp(self): | |
return self._tmp | |
@tmp.setter | |
def tmp(self, tmp): | |
if isinstance(tmp, float): | |
self._tmp = tmp | |
elif isinstance(tmp, int): | |
self._tmp = float(tmp) | |
@property | |
def last_upd(self): | |
return self._dt | |
@last_upd.setter | |
def last_upd(self, dt): | |
if isinstance(dt, str): | |
self._dt = dt | |
class sensor_hum: | |
def __init__(self, hum, dt): | |
self._hum = hum | |
self._dt = dt | |
@property | |
def hum(self): | |
return self._hum | |
@hum.setter | |
def hum(self, hum): | |
if isinstance(hum, float): | |
self._hum = hum | |
elif isinstance(hum, int): | |
self._hum = float(hum) | |
@property | |
def last_upd(self): | |
return self._dt | |
@last_upd.setter | |
def last_upd(self, dt): | |
if isinstance(dt, str): | |
self._dt = dt | |
# pylint: disable=no-name-in-module,wrong-import-order | |
def setup(): | |
global tmp_cl, hum_cl, on_usb, use_sound, use_leds, wait_for_zero_sec, my_debug, interval, TZ_OFFSET, COUNTRY, STATE | |
TAG = 'setup(): ' | |
on_usb = is_usb() | |
use_sound = True if int(os.getenv("USE_SOUND")) else False | |
use_leds = True if int(os.getenv("USE_LEDS")) else False | |
wait_for_zero_sec = True if int(os.getenv("WAIT_FOR_ZERO_SEC")) else False | |
my_debug = True if int(os.getenv("MY_DEBUG")) else False | |
interval = int(os.getenv("INTERVAL_SECONDS")) | |
TZ_OFFSET = int(os.getenv("TZ_OFFSET")) | |
COUNTRY = os.getenv("COUNTRY") | |
STATE = os.getenv("STATE") | |
if my_debug: | |
print(TAG+f"use_sound= {use_sound}") | |
print(TAG+f"use_leds= {use_leds}") | |
print(TAG+f"wait_for_zero_sec= {wait_for_zero_sec}") | |
print(TAG+f"Interval set for {interval} seconds") | |
print(TAG+"Display height= {}, width= {}".format(height, width)) # result: height 127, width 295 | |
# h0 = height // 6 # 127 // 6 = 21 20 + 21 = 41 , 20 + (2 x 21) = 62, 20 + (3*21)= 83, 20 + (4x21)= 104 | |
# hlist = [h0, h0*3, h0*5] | |
hlist = [20, 41, 62, 83, 104] | |
for _ in range (len(hlist)): | |
magtag.add_text( | |
#text_font="/fonts/Arial-12.pcf", | |
text_position=( | |
10, | |
hlist[_], | |
), | |
text_scale=2, | |
) | |
# Create instances of the sensor_tmp and sensor_hum classes | |
tmp_cl = sensor_tmp(0.00, "") # create class instance with default values | |
hum_cl = sensor_hum(0.00, "") # same | |
text_items = ["Sensor data to Google", "using", "Pushingbox.com", "(c) 2024 @PaulskPt", f"USB connected: {"Yes" if on_usb else "No "}"] | |
for i in range(len(text_items)): | |
magtag.set_text(text_items[i], i, auto_refresh = False) # Display the dt, tm and tz | |
time.sleep(1) # to prevent RuntimeError Refresh too soon | |
try: | |
magtag.display.refresh() # refresh the display | |
except RuntimeError: | |
print(TAG+"RuntimeError") | |
pass # reason: Refresh too soon | |
# +-----------------------------------------------------------+ | |
# | CONNECT TO WiFi | | |
# +-----------------------------------------------------------+ | |
wifi.AuthMode.WPA2 # set only once | |
ssid = os.getenv("CIRCUITPY_WIFI_SSID") | |
print(TAG+f"Connecting to AP {os.getenv("CIRCUITPY_WIFI_SSID")}") | |
wifi_cnt = 0 | |
while not wifi_is_connected(): | |
if not do_connect(): | |
print(TAG+f"WiFi failed to connect to {ssid}") | |
wifi_cnt += 1 | |
if wifi_cnt >= 5: | |
print(TAG+f"tried {wifi_cnt} times to connect WiFi but failed. Exiting...") | |
time.sleep(3) | |
break | |
if wifi_is_connected(): | |
time.sleep(2) | |
ipv4 = ipaddress.ip_address("8.8.8.8") | |
ping_time = 0.0 | |
ping_cnt = 0 | |
while ping_time is 0.00: | |
ping_time = wifi.radio.ping(ipv4) | |
if ping_time is None: # prevent crash | |
ping_time = 0.0 | |
if ping_time < 0.001: | |
ping_cnt += 1 | |
if ping_cnt >= 10: | |
print(TAG+f"Ping to Google failed. Tried {ping_cnt} times") | |
break | |
if ping_time > 0.00: | |
print(TAG+f"Ping google.com: {ping_time} ms") | |
if is_NTP(): | |
if not my_debug: | |
print(TAG + "We have NTP") | |
if is_INT_RTC(): | |
if not my_debug: | |
print(TAG + "We have an internal RTC") | |
print(TAG + "Going to set internal RTC") | |
set_INT_RTC() | |
dummy = is_dst( time.localtime(time.time()) ) | |
if SYS_RTC_is_set: | |
if my_debug: | |
print(TAG + "and the internal RTC is set from an NTP server") | |
def blink_and_button_test(clr=None): | |
TAG= "blink_test(): " | |
if my_debug: | |
print(TAG+f"param clr= {clr} = {clr_dict[clr]}") | |
cnt = 0 | |
if clr is None: # Do the test | |
while True: | |
for i, b in enumerate(magtag.peripherals.buttons): | |
if not b.value: | |
print("Button %c pressed" % chr((ord("A") + i))) | |
magtag.peripherals.neopixel_disable = False | |
magtag.peripherals.neopixels.fill(button_colors[i]) | |
magtag.peripherals.play_tone(button_tones[i], 0.25) | |
break | |
else: | |
magtag.peripherals.neopixels.fill(button_colors[BLK]) # switch neopixels to black (off) | |
magtag.peripherals.neopixel_disable = True | |
time.sleep(0.01) | |
cnt += 1 | |
if cnt >= len(button_colors): | |
print(f"Exiting function: {TAG[:-4]}") | |
break | |
def blink_leds(clr=BLK): | |
if not use_leds: | |
return | |
TAG= "blink_leds(): " | |
if isinstance(clr, int): | |
le = len(button_colors) | |
if clr < 0: | |
clr = 0 | |
if clr >= le: | |
clr = le -1 | |
if my_debug: | |
print(TAG+f"param clr= {clr} = {clr_dict[clr]}") | |
magtag.peripherals.neopixel_disable = False | |
magtag.peripherals.neopixels.fill(button_colors[clr]) | |
if use_sound and clr != BLK: # Only sound tone if color is not black | |
magtag.peripherals.play_tone(button_tones[clr], 0.25) | |
time.sleep(0.01) | |
magtag.peripherals.neopixels.fill(button_colors[BLK]) # switch neopixels to black (off) | |
magtag.peripherals.neopixel_disable = True | |
""" | |
* @brief This function checks if exists an ntp object | |
* If so, it retrieves a datetime stamp from an NTP server | |
* and sets NTP_dt to the retrieved datetime stamp | |
* It then also sets the NTP_dt_is_set flag | |
* | |
* @param state | |
* | |
* @return boolean | |
""" | |
def is_NTP(): | |
TAG = "is_NTP(): " | |
global NTP_dt_is_set, NTP_dt, ntp | |
ret = False | |
try: | |
if ntp is not None: | |
if not NTP_dt_is_set: | |
if my_debug: | |
print(TAG+f"type(ntp)= {type(ntp)}") | |
print(TAG+f"ntp.datetime= {ntp.datetime}") | |
NTP_dt = ntp.datetime | |
if my_debug: | |
print(TAG + f"NTP_dt: {NTP_dt}") | |
NTP_dt_is_set = True | |
ret = True if NTP_dt is not None else False | |
except OSError as e: | |
print(f"is_NTP() error: {e}") | |
return ret | |
""" | |
* @brief This function checks if the passed | |
* param tm falls between the limits of | |
* 'daylight-saving-time' (dst) of the | |
* actual country. | |
* This function: | |
* - uses the dt dictionary, | |
* which has been imported from the file | |
* dst_prt.py | |
* - If global variable my_debug is True, prints to REPL: | |
* - the dst datetime limits to the REPL | |
* - nr of days to the start of dst period. | |
* - nr of days to the end of dst period. | |
* - returns True if the given | |
* date is within the dst limits. | |
* - returns False if the given | |
* date is not within the dst limits. | |
* | |
* @param tm (a time structure) | |
* | |
* @return Boolean | |
""" | |
def is_dst(tm): | |
global ntp, dst_offset, NTP_dt | |
TAG = "is_dst(): " | |
if not my_debug: | |
print(TAG+f"param tm= {tm}") | |
yy = tm.tm_year | |
dst_org = dst_offset # get original value | |
if not yy in dst.keys(): | |
print( | |
TAG | |
+ f"year: {yy} not in dst dictionary {dst.keys()}.\nUpdate the dictionary! Exiting..." | |
) | |
#raise SystemExit | |
else: | |
dst_start_end = dst[yy] | |
if not my_debug: | |
print(TAG + f"year: {yy}, dst_start_end: {dst_start_end}") | |
cur_dt = time.localtime() | |
dst_start1 = dst_start_end[0] | |
dst_end1 = dst_start_end[1] | |
dst_start2 = time.localtime(dst_start1) | |
dst_end2 = time.localtime(dst_end1) | |
if my_debug: | |
print( | |
TAG | |
+ "dst_start1: {:4d}-{:02d}-{:02d} {:02d}:{:02d}:{:02d}".format( | |
dst_start2.tm_year, | |
dst_start2.tm_mon, | |
dst_start2.tm_mday, | |
dst_start2.tm_hour, | |
dst_start2.tm_min, | |
dst_start2.tm_sec, | |
) | |
) | |
print( | |
TAG | |
+ "current date: {:4d}-{:02d}-{:02d} {:02d}:{:02d}:{:02d}".format( | |
cur_dt.tm_year, | |
cur_dt.tm_mon, | |
cur_dt.tm_mday, | |
cur_dt.tm_hour, | |
cur_dt.tm_min, | |
cur_dt.tm_sec, | |
) | |
) | |
print( | |
TAG | |
+ "dst_end1: {:4d}-{:02d}-{:02d} {:02d}:{:02d}:{:02d}".format( | |
dst_end2.tm_year, | |
dst_end2.tm_mon, | |
dst_end2.tm_mday, | |
dst_end2.tm_hour, | |
dst_end2.tm_min, | |
dst_end2.tm_sec, | |
) | |
) | |
if my_debug: | |
print( | |
TAG | |
+ f"year: {tm.tm_year}, dst start: {dst_start2}, dst end: {dst_end2}" | |
) | |
current_time = time.time() | |
if current_time > dst_start1 and current_time < dst_end1: | |
dst_new = 1 | |
else: | |
dst_new = 0 | |
if dst_new != dst_org: | |
dst_offset = dst_new | |
print(TAG+f"dst_org {dst_org}, dst_new: {dst_new}. We are going to set the ntp object with timezone offset: {TZ_OFFSET if dst_offset else 0} hour(s)") | |
ntp = adafruit_ntp.NTP(pool, tz_offset=TZ_OFFSET if dst_offset else 0) | |
set_INT_RTC() | |
ret = True if dst_offset == 1 else False | |
if not my_debug: | |
# print(TAG+f"dst_offset: {dst_offset}") | |
s = "Yes" if dst_offset == 1 else "No" | |
print( | |
TAG | |
+ f"Are we in daylight saving time for country: '{COUNTRY}', state: '{STATE}' ? {s}" | |
) | |
myDate = Date() | |
curr_yr = time.localtime(current_time)[0] | |
curr_mon = time.localtime(current_time)[1] | |
curr_mday = time.localtime(current_time)[2] | |
curr_dt = (curr_mday, curr_mon, curr_yr) | |
start_yr = time.localtime(dst_start1)[0] | |
start_mon = time.localtime(dst_start1)[1] | |
start_mday = time.localtime(dst_start1)[2] | |
start_dt = (start_mday, start_mon, start_yr) | |
end_yr = time.localtime(dst_end1)[0] | |
end_mon = time.localtime(dst_end1)[1] | |
end_mday = time.localtime(dst_end1)[2] | |
end_dt = (end_mday, end_mon, end_yr) | |
if dst_offset: | |
days_to_dst_start = myDate.getDifference(curr_dt, start_dt) | |
days_to_dst_end = myDate.getDifference(curr_dt, end_dt) | |
else: | |
days_to_dst_start = myDate.getDifference(curr_dt, start_dt) | |
days_to_dst_end = myDate.getDifference(curr_dt, end_dt) | |
print(TAG+"Days to start of daylight saving time period: {:3d}".format(days_to_dst_start)) | |
print(TAG+"Days to end of daylight saving time period: {:3d}".format(days_to_dst_end)) | |
return ret | |
def dt_fm_rtc(): | |
TAG = "dt_fm_rtc(): " | |
dt = time.localtime() | |
dts = "{:d}-{:02d}-{:02d}T{:02d}:{:02d}:{:02d}Z".format(dt.tm_year, dt.tm_mon, dt.tm_mday, dt.tm_hour, dt.tm_min, dt.tm_sec) | |
if not my_debug: | |
print(TAG+f"dts= {dts}") #, dt.tm_isdst= {dt.tm_isdst}") | |
return dts | |
""" | |
* @brief function returns True | |
* if RTC object instance mRTC exists | |
* | |
* @param state | |
* | |
* @return None | |
""" | |
def is_INT_RTC(): | |
if rtc_bi is not None: | |
return True | |
return False | |
""" | |
* @brief This function sets the internal | |
* realtime clock | |
* It retrieves the datetime stamp from an NTP server | |
* on internet | |
* | |
* @param state | |
* | |
* @return None | |
""" | |
def set_INT_RTC(): | |
global rtc_bi, rtc_set, curr_tm, dts | |
if not set_SYS_RTC: | |
return | |
TAG = "set_INT_RTC(): " | |
s1 = "Internal (SYS) RTC is set from " | |
s2 = "datetime stamp: " | |
dt = None | |
internal_RTC = True if is_INT_RTC() else False | |
if internal_RTC: | |
try: | |
dt = ntp.datetime | |
if not rtc_set: | |
rtc_bi.datetime = dt | |
rtc_set = True | |
except OSError as e: | |
err = e.args[0] | |
if err == -2: # gaierror | |
print(TAG+"Name or service not known. Exiting function") | |
return | |
elif err == 116: | |
print(TAG+"NTP timed out. Exiting function.") | |
return | |
else: | |
print( | |
TAG + f"Error while trying to set internal RTC from NTP datetime: {e}" | |
) | |
raise | |
except Exception as e: | |
raise | |
if wait_for_zero_sec: # see flag at start of this func | |
print(TAG+"Waiting for time.localtime seconds reaching 0 ...") | |
while True: | |
t = time.localtime() | |
if t[5] == 0: # Wait until seconds is almost 60 (0) | |
# print("t[tm_sec]=", t[5]) | |
break | |
print(TAG+f"finished waiting for zero second") | |
curr_tm = time.time() # get the time in seconds since epoch (set curr_tm only at startup) | |
rtc_set = True | |
# Prepare datetime for funct get_th_direct() | |
# format: 2022-08-10T16:40:16Z | |
#dts = dt[:4] + "-" + dt[5:7] + "-" + dt[8:10] + "T" + resp_lst[1][:2] + ":" + resp_lst[1][3:5] + ":" + resp_lst[1][6:8] + "Z" | |
# dts = dt[:4] + "-" + dt[5:7] + "-" + dt[8:10] + "T" + resp_lst[1][:2] + ":" + resp_lst[1][3:5] + ":" + resp_lst[1][6:8] + "Z" | |
dts = "{}-{:02d}-{:02d}T{:02d}:{:02d}:{:02d}Z".format(dt.tm_year, dt.tm_mon, dt.tm_mday, dt.tm_hour, dt.tm_min, dt.tm_sec) | |
SYS_dt = rtc_bi.datetime | |
if my_debug: | |
print(TAG + f"rtc_bi.datetime: {rtc_bi.datetime}") | |
# print(TAG+f"SYS_dt: {SYS_dt}") | |
SYS_RTC_is_set = True | |
if SYS_dt.tm_year >= 2000: | |
print(TAG + s1 + "NTP service " + s2) | |
dt = SYS_dt | |
if not my_debug: | |
print(TAG + "{:d}/{:02d}/{:02d}".format(dt.tm_mon, dt.tm_mday, dt.tm_year)) | |
print( | |
TAG | |
+ "{:02d}:{:02d}:{:02d} weekday: {:s}".format( | |
dt.tm_hour, dt.tm_min, dt.tm_sec, rtc_DOW[dt.tm_wday] | |
) | |
) | |
if internal_RTC: | |
print(TAG + "Note that NTP weekday starts with 0") | |
def get_th_direct(): | |
global t_dict, h_dict, curr_tm, tmp_old, hum_old, tmp_cl, hum_cl, sensor | |
# datetime e.g.: 2022-08-10T16:40:16Z | |
TAG = "get_th_direct(): " | |
dts = dt_fm_rtc() # get datetime from builtin rtc | |
# -------------------------------------------------------------- | |
if not sensor: | |
try: | |
sensor = adafruit_ahtx0.AHTx0(i2c) | |
except ValueError as e: | |
print(TAG+f"Error: {e}. Check wiring!") | |
if sensor: | |
try: | |
tmp = sensor.temperature | |
hum = sensor.relative_humidity | |
if my_debug: | |
blink_leds(YLW) | |
tmp_cl.tmp = tmp | |
tmp_cl.last_upd = dts | |
if tmp != tmp_old: | |
tmp_old = tmp | |
# ------------------ | |
hum_cl.hum = hum | |
hum_cl.last_upd = dts | |
if hum != hum_old: | |
hum_old = hum | |
# ----------------- | |
if my_debug: | |
print(TAG+f"updated_at: {tmp_cl.last_upd}") | |
print(TAG+f"Temperature: {tmp_cl.tmp}") | |
print(TAG+f"Humidity: {hum_cl.hum}") | |
except ValueError as e: | |
print(TAG+f"Error: {e}. Check wiring!") | |
pass | |
def pr_th_msg(): | |
global stat_result | |
TAG = "pr_th_msg(): " | |
if stat_result is None: | |
stat_result = "" | |
ret = True | |
upd_dt = tmp_cl.last_upd # [:10] # e.g.: 2022-08-10T16:40:16Z | |
# ----------------- | |
tmp = tmp_cl.tmp | |
tmp_s = str(tmp) | |
# ----------------- | |
hum = hum_cl.hum | |
hum_s = str(hum) | |
# ---------------- | |
text_items = ["latest sensor data "+stat_result, "-" * 23, upd_dt, "Temperature: "+tmp_s+" C", "Humidity: "+hum_s+" %"] | |
magtag.remove_all_text | |
for i in range(len(text_items)): | |
magtag.set_text(text_items[i], i, auto_refresh = False) # Display the dt, tm and tz | |
cnt = 0 | |
while True: | |
try: | |
magtag.display.refresh() # refresh the display | |
cnt += 1 | |
if cnt >= 10: | |
ret = False | |
break | |
except RuntimeError: | |
# print(TAG+"RuntimeError") | |
pass # reason: Refresh too soon | |
return ret | |
def send_to_pushingbox(): | |
global msg_sent, upd_dt_old, tmp_old, hum_old, stat_result | |
TAG = "send_to_pushingbox(): " | |
ret = True | |
tmp_s = None | |
hum_s = None | |
response = None | |
stat_result = None | |
devid = os.getenv("PUSHING_BOX_DEVID") # device ID on Pushingbox for our Scenario | |
upd_dt = tmp_cl.last_upd # [:10] # e.g.: 2022-08-10T16:40:16Z | |
# -------------------------------------------------------------- | |
tmp = tmp_cl.tmp | |
tmp_s = str(tmp) | |
if my_debug: | |
print(TAG+f"tmp_s= \'{tmp_s}\', tmp_old= {tmp_old}") | |
# -------------------------------------------------------------- | |
hum = hum_cl.hum | |
hum_s = str(hum) | |
if my_debug: | |
print(TAG+f"hum_s= \'{hum_s}\', hum_old= {hum_old}") | |
# -------------------------------------------------------------- | |
# le_old = len(upd_dt_old) | |
# if (le_old > 0) and (tmp == tmp_old) and (hum == hum_old): # and upd_dt == upd_dt_old | |
if (upd_dt_old == upd_dt) and (tmp == tmp_old) and (hum == hum_old): # and upd_dt == upd_dt_old | |
print(TAG+"datetime stamp unchanged. Waiting for new sensor data...") | |
return ret # We don't want to send duplicates | |
else: | |
upd_dt_old = upd_dt # | |
#upd_tm = t_dict["updated_at"][11:19] | |
msg_sent += 1 # increase the messages sent count | |
# dteData = upd_dt # Added 2024-03-22 because this variable was missing. | |
# ?date=$date$&time=$time$&temp=$temp$&hum=$hum$ | |
s = "http://api.pushingbox.com/pushingbox?devid=" | |
s += devid | |
s += "&date=\"" + upd_dt + "\"" | |
s += "&temp=" + tmp_s | |
s += "&hum=" + hum_s | |
if my_debug: | |
print(TAG+upd_dt, end='') | |
print(". Sending Data message nr: ", end='') | |
print(msg_sent, end='') | |
print(" to middle-man server...", end='\n') | |
print(TAG+"Going to send:", end='') | |
print("\n\""+s, end='') | |
print("\"", end='\n') # To complete the message to the Serial (REPL) window | |
print(TAG+"Data Sent") | |
try: | |
network = magtag.network | |
response = network.fetch(s) # Get the spreadsheet partly | |
except OSError as e: | |
print(TAG+f"Error: {e}") | |
if e.args[0] == -2: # gaierror | |
# See: https://docs.circuitpython.org/_/downloads/en/6.3.x/pdf/, page 216 | |
return # do nothing | |
except RuntimeError as e: # can be activated by adafruit_requests, OutOfRetries error | |
# or by get_socket. RuntimeError, EHOSTUNREACH errno 118 | |
print(TAG+f"Error: {e}") | |
return # do nothing | |
if my_debug: | |
print() | |
print(TAG+f"response= {response}") | |
if response: | |
le = len(response.text) | |
if le > 0: | |
n = response.text.find("404") | |
print(TAG,end='') | |
if n >=0: | |
print("error 404: file not found on this server.") | |
else: | |
print(f"response.text[:100]= {response.text[:100]}", end='') | |
print(" [...] ", end='') | |
print(f"{response.text[-100:]}", end='\n') | |
status = response.status_code | |
stat_result = "OK" if status == 200 else "NO" | |
print() | |
s1 = "response.status_code=" | |
s2 = "{} (= {})".format(status, stat_result) | |
print(TAG+f"{s1} {s2}") | |
if status == 200: | |
blink_leds(GRN) | |
else: | |
blink_leds(RED) | |
if my_debug: | |
pr_msg(["send result:", s2]) | |
response = None | |
if my_debug: | |
print(TAG+f"upd_dt= {upd_dt}, tmp_s= {tmp_s}, hum_s= {hum_s}") | |
pr_th_msg() | |
return ret | |
def yes_no(nr): | |
ret = None | |
y = "Yes" | |
n = "No " | |
if isinstance(nr, int): | |
if nr >= 0 and nr <= 3: | |
if nr == SOUND_IDX: | |
ret = y if use_sound else n | |
if nr == LEDS_IDX: | |
ret = y if use_leds else n | |
if nr == ZEROSEC_IDX: | |
ret = y if wait_for_zero_sec else n | |
if nr == DEBUG_IDX: | |
ret = y if my_debug else n | |
return ret | |
def pr_buttons(): | |
text_items = [ | |
"Btn: Function:", | |
"A: sound", | |
"B: LEDs", | |
"C: wait for zero sec", | |
"D: debug texts"] | |
pr_msg(text_items) | |
def pr_flags(): | |
TAG= "pr_flags(): " | |
itms_lst = ["sound", "LEDs", "start at zero sec", "print debug", ] | |
le = len(itms_lst) | |
print("\nStatus of global flags: (set in file settings.toml):") | |
for _ in range(le): | |
print(TAG+"{:17s}: {:s}".format(itms_lst[_], yes_no(_))) | |
print() | |
text_items = ["global flags "] | |
for _ in range(le): | |
s = "{:17s}: {:s}".format(itms_lst[_], yes_no(_)) | |
text_items.append(s) | |
for i in range(len(text_items)): | |
magtag.set_text(text_items[i], i, auto_refresh = False) # Display the dt, tm and tz | |
time.sleep(1) # to prevent RuntimeError Refresh too soon | |
cnt = 0 | |
while True: | |
try: | |
magtag.display.refresh() # refresh the display | |
cnt += 1 | |
if cnt >= 10: | |
break | |
except RuntimeError: | |
# print(TAG+"RuntimeError") | |
pass # reason: Refresh too soon | |
def is_usb(): | |
# Test if we're connected to USB | |
# If an error occurs we are on USB | |
ret = False | |
try: | |
from storage import remount | |
remount("/", False) | |
except (RuntimeError) as e: | |
ret = True | |
print(f"is_usb(): Are we connected to USB? {"Yes" if ret else "No"}") | |
return ret | |
def do_connect(): | |
global ip | |
TAG = "do_connect(): " | |
ret = False | |
# Get env variables from file settings.toml | |
ssid = os.getenv("CIRCUITPY_WIFI_SSID") | |
pw = os.getenv("CIRCUITPY_WIFI_PASSWORD") | |
s__ip = "" | |
try: | |
wifi.radio.connect(ssid=ssid, password=pw) | |
except ConnectionError as e: | |
print(TAG+f"WiFi connection Error: \'{e}\'") | |
except Exception as e: | |
print(TAG+f"Error: {dir(e)}") | |
ip = wifi.radio.ipv4_address | |
if ip: | |
s__ip = str(ip) | |
ret = True | |
if my_debug: | |
print(TAG+f"connected to \'{ssid}\'. IP: {s__ip}") | |
return ret | |
def wifi_is_connected(): | |
global ip | |
s__ip = str(ip) | |
return True if s__ip is not None and len(s__ip) > 0 and s__ip != '0.0.0.0' else False | |
def pr_msg(msg): | |
text_items = [] | |
le_max = 5 | |
if isinstance(msg, list): | |
le_msg = len(msg) | |
if le_msg > 0 and le_msg <= le_max: | |
for _ in range(len(msg)): | |
text_items.append(msg[_]) | |
le = len(text_items) | |
if le_max - le > 0: # fill up with blank lines | |
for _ in range(le_max - le): | |
text_items.append(" ") | |
for i in range(len(text_items)): | |
magtag.set_text(text_items[i], i, auto_refresh = False) # Display the dt, tm and tz | |
time.sleep(1) # to prevent RuntimeError Refresh too soon | |
cnt = 0 | |
while True: | |
try: | |
magtag.display.refresh() # refresh the display | |
cnt += 1 | |
if cnt >= 10: | |
break | |
except RuntimeError: | |
# print(TAG+"RuntimeError") | |
pass # reason: Refresh too soon | |
def wr_to_toml(itm): | |
TAG= "wr_to_toml(): " | |
toml_f = "settings.toml" | |
if on_usb: | |
s1 = "Writing to file" | |
s2 = "works only when" | |
s3 = "not connected to USB" | |
print(TAG+f"{s1}{toml_f} {s2} {s3}") | |
pr_msg([s1, toml_f, s2, s3]) | |
pr_th_msg() # rewrite the temperature & humidity page | |
return False | |
ret = True | |
delay = 3 | |
itms = [("WAIT_FOR_ZERO_SEC", wait_for_zero_sec), ("MY_DEBUG", my_debug)] | |
print(TAG+f"param rcvd: itm= {itm}") | |
itm_s = itms[itm][0] | |
val = itms[itm][1] | |
val_s = "1" if val == True else "0" | |
print(TAG+f"Trying to write to file: {toml_f}, item: \"{itm_s}\" with value: {val_s}") | |
# Write | |
try: | |
from cptoml import put | |
from storage import remount | |
remount("/", False) | |
#put("CIRCUITPY_PYSTACK_SIZE", 7000) # To set an item in root table | |
put(itm_s, val_s) #, "subtable1", comment="This is useless") # To set item1 in subtable1 with comment | |
remount("/", True) | |
pr_msg([itm_s, "value: " + val_s, "successfully", "written to:", toml_f]) | |
print("Software reset in %d seconds" % delay) | |
time.sleep(delay) | |
supervisor.reload() | |
except (RuntimeError, ImportError, OSError) as e: | |
print(TAG+f"Error: {e}") | |
ret = False | |
return ret | |
def main(): | |
global curr_tm, use_sound, use_leds, wait_for_zero_sec, my_debug, interval | |
TAG = 'main(): ' | |
setup() | |
curr_tm = time.time() # set curr_tm for the first time | |
start = True | |
msg_sent = False | |
delay = 3 | |
# blink_and_button_test() # Test the Magtag LEDs | |
pr_buttons() | |
pr_flags() | |
toml_zero_sec = 0 | |
toml_debug = 1 | |
wifi_cnt = 0 | |
doit = False | |
while True: | |
try: | |
while not wifi_is_connected(): | |
if do_connect(): | |
break | |
else: | |
wifi_cnt += 1 | |
if wifi_cnt >= 5: | |
print(TAG+f"WiFi connection failed. Tried {wifi_cnt} times") | |
raise RuntimeError | |
if magtag.peripherals.button_a_pressed: | |
use_sound = not use_sound # toggle sound | |
s1 = "button A pressed." | |
s2 = "sound {:s}".format(yes_no(SOUND_IDX)) | |
print(TAG+f"{s1} {s2}") | |
pr_msg([s1, s2]) | |
pr_th_msg() # rewrite the temperature & humidity page | |
if magtag.peripherals.button_b_pressed: | |
use_leds = not use_leds # toggle leds | |
s1 = "button B pressed." | |
s2 = "LEDs {:s}".format(yes_no(LEDS_IDX)) | |
print(TAG+f"{s1} {s2}") | |
pr_msg([s1, s2]) | |
pr_th_msg() # rewrite the temperature & humidity page | |
if magtag.peripherals.button_c_pressed: | |
wait_for_zero_sec = not wait_for_zero_sec | |
print(TAG+"button C pressed. Start time wait for zero seconds {:s}".format(yes_no(ZEROSEC_IDX))) | |
wr_to_toml(toml_zero_sec) | |
if magtag.peripherals.button_d_pressed: | |
my_debug = not my_debug | |
print(TAG+"button d pressed. Debug print statements {:s}".format(yes_no(DEBUG_IDX))) | |
wr_to_toml(toml_debug) | |
if not rtc_set: | |
set_INT_RTC() | |
# get_time_fm_aio() | |
if rtc_set: | |
ct = time.time() # rtc_bi.datetime | |
c_diff = ct - curr_tm | |
dt1 = interval // 6 # default: 3600 seconds. 3600 // 6 = 600 seconds = 10 minutes. See setup(). | |
dt2 = interval # default: 3600 seconds = 1 hour | |
c1 = c_diff % dt1 | |
c2 = c_diff % dt2 | |
# print(TAG+"c1: {:4d}, dt1: {:4d}, c1 % 10 = {:2d}. c1 == dt1: {:s}".format(c1, dt1, c1 % 10, "True" if (c1 == dt1) else "False")) | |
# print(TAG+"c2: {:4d}, dt2: {:4d}, c2 % 10 = {:2d}. c2 == dt2: {:s}".format(c2, dt2, c2 % 10, "True" if (c1 == dt1) else "False")) | |
if c1 % 10 == 0: | |
if msg_sent: | |
msg_sent = False | |
# print(TAG+f"ct= {ct}, curr_tm= {curr_tm}. Difference= {ct - curr_tm} secs.") | |
# print(TAG+f"c_diff % {dt1}= {c1}. c_diff % {dt2}= {c2}. Looping...") | |
print(TAG+"c_diff % {:3d}= {:4d}, c_diff % {:4d}= {:4d}. Looping...".format(dt1, c1, dt2, c2)) | |
# doit = True if (c2 == dt2) else False | |
if c2 == 0: | |
doit = True | |
else: | |
doit = False | |
if start or (not sensor) or (doit) and (not msg_sent): | |
start = False | |
blink_leds() # switch off LEDs | |
get_th_direct() # sensor directly connected to MAGTAG board via I2C/Stemma_QT | |
gc.collect() | |
if not send_to_pushingbox(): | |
raise KeyboardInterrupt | |
else: | |
msg_sent = True | |
# if c2 == 30: | |
# sys.exit() # Temporary forced end of execution | |
if doit: | |
set_INT_RTC() | |
curr_tm = ct | |
time.sleep(1) | |
except ImportError: # e.g.: no module named 'platform' (in file :/lib/Adafruit_IO/Client.py, line 24) | |
pass | |
except KeyboardInterrupt: | |
raise SystemExit | |
if __name__ == '__main__': | |
main() |
# SPDX-FileCopyrightText: 2020 Brent Rubell, written for Adafruit Industries | |
# | |
# SPDX-License-Identifier: Unlicense | |
# | |
# File very modified by @PaulskPt. Latest updates on: 2022-08-11, 2024-03-23 | |
# (Github @PaulskPt) | |
# Last CircuitPython update on: 2024-03-22. Updated CPY to V9.0.0 | |
# This script has functionality to "hotplug-ing" the sensor. | |
# 2024-03-24 15h00 in function send_to_pushingbox() added variable stat_result. If stat == 200, stat_result | |
# will show the text "OK" in the top right of the MAGTAG page "latest sensor data". If stat != 200, stat_result | |
# will show the text "NO" (meaning: fail). | |
# 2024-03-25 13h20 added global variables use_sound and use_leds | |
# Button A will toggle sound | |
# Button B will toggle LEDs | |
# Button C will toggle the global variable wait_for_zero_sec. Then tries to write this setting to file: settings.toml. | |
# Button D will toggle the global variable my_debug. Then tries to write this setting to file: settings.toml. | |
# Note that file settings.toml can only be updated from within this script when the MAGTAG is not connected to USB. | |
# In function send_to_pushingbox() the response is 200 (OK), the LEDs will blink green if use_leds is True. | |
# the leds will blink red if the response is other than 200. | |
# For module cptoml see: https://github.com/beryllium-org/cptoml | |
# When reading the sensor the LEDs of the MAGTAG will blink one time in color Yellow. | |
# Depending on the global variable use_sound, a tone will be produced or not. | |
# When the datetime stamp and sensor data successfully are sent to Pushingbox.com, the LEDs of the MAGTAG will blink | |
# Depending on the global variable use_sound, a tone will be produced or not. | |
# one time Green. | |
# Added function is_usb() that ckecks if the board is connected to USB or not. | |
""" | |
The Adafruit MAGTAG contains an ESP32-S2 WROVER chip. | |
Note: On 2022-08-10 at 17h12 utc+1 the Google Apps Script system reported that the project | |
'DataToGoogle_MAGTAG', deployment version 6, executed successfully. | |
This execution came from Pushingbox.com that was triggered by this CircuitPython script (see function 'send_data_to_google()') | |
Note also that the Google Apps Script deployment was set that it was available to 'anyone' (with the link). | |
On 2024-03-24, in Google Apps Scripts I had to create a new deployment (version 7). It executed successfully. | |
""" | |
import sys | |
import os | |
import supervisor | |
import board | |
import time | |
import wifi | |
import rtc | |
import ipaddress | |
from adafruit_magtag.magtag import MagTag | |
import adafruit_ahtx0 | |
# Global flags (see setup()): | |
use_sound = None | |
use_leds = None | |
wait_for_zero_sec = None | |
my_debug = None | |
on_usb = None | |
SOUND_IDX = 0 | |
LEDS_IDX = 1 | |
ZEROSEC_IDX = 2 | |
DEBUG_IDX = 3 | |
sensor = None | |
stat_result = None | |
interval = None | |
ip = 0 | |
i2c = board.STEMMA_I2C() | |
try: | |
sensor = adafruit_ahtx0.AHTx0(i2c) | |
except ValueError as e: | |
print(f"Global. Error: {e}. Check wiring!") | |
pass | |
# Create an instance of the MagTag class | |
magtag = MagTag() | |
height = magtag.graphics.display.height -1 | |
width = magtag.graphics.display.width -1 | |
# Less brillance than originally (mod by @paulsk) | |
b1=25 # originally 255 | |
b2=15 # idem 150 | |
b3=18 # idem 180 | |
red_tpl = (b2, 0, 0) | |
ylw_tpl = (b1, b2, 0) | |
grn_tpl = (0, b2, 0) | |
blu_tpl = (0, 0, b2) | |
blk_tpl = (0,0,0) | |
RED = 0 | |
YLW = 1 | |
GRN = 2 | |
BLU = 3 | |
BLK = 4 | |
clr_dict = { | |
RED : "RED", | |
YLW : "YLW", | |
GRN : "GRN", | |
BLU : "BLU", | |
BLK : "BLK" | |
} | |
button_colors = (red_tpl, ylw_tpl, grn_tpl, blu_tpl, blk_tpl) # last tuple added for color black | |
button_tones = (1047, 1318, 1568, 2093, 440) | |
msg_sent = 0 | |
tmp_old = 0.00 | |
hum_old = 0.00 | |
upd_dt_old = "" | |
dts = "" # Set by get_time_fm_aio() and used in get_th_direct() | |
curr_tm = None # struct_time | |
rtc_set = False | |
rtc_bi = rtc.RTC() # create an instance of the built-in RTC | |
weekdays = {0:"Monday", 1:"Tuesday",2:"Wednesday",3:"Thursday",4:"Friday",5:"Saturday",6:"Sunday"} | |
tmp_cl = None | |
hum_cl = None | |
class sensor_tmp: | |
def __init__(self, tmp, dt): | |
self._tmp = tmp | |
self._dt = dt | |
@property | |
def tmp(self): | |
return self._tmp | |
@tmp.setter | |
def tmp(self, tmp): | |
if isinstance(tmp, float): | |
self._tmp = tmp | |
elif isinstance(tmp, int): | |
self._tmp = float(tmp) | |
@property | |
def last_upd(self): | |
return self._dt | |
@last_upd.setter | |
def last_upd(self, dt): | |
if isinstance(dt, str): | |
self._dt = dt | |
class sensor_hum: | |
def __init__(self, hum, dt): | |
self._hum = hum | |
self._dt = dt | |
@property | |
def hum(self): | |
return self._hum | |
@hum.setter | |
def hum(self, hum): | |
if isinstance(hum, float): | |
self._hum = hum | |
elif isinstance(hum, int): | |
self._hum = float(hum) | |
@property | |
def last_upd(self): | |
return self._dt | |
@last_upd.setter | |
def last_upd(self, dt): | |
if isinstance(dt, str): | |
self._dt = dt | |
# pylint: disable=no-name-in-module,wrong-import-order | |
def setup(): | |
global tmp_cl, hum_cl, on_usb, use_sound, use_leds, wait_for_zero_sec, my_debug, interval | |
TAG = 'setup(): ' | |
on_usb = is_usb() | |
use_sound = True if int(os.getenv("USE_SOUND")) else False | |
use_leds = True if int(os.getenv("USE_LEDS")) else False | |
wait_for_zero_sec = True if int(os.getenv("WAIT_FOR_ZERO_SEC")) else False | |
my_debug = True if int(os.getenv("MY_DEBUG")) else False | |
interval = int(os.getenv("INTERVAL_SECONDS")) | |
if my_debug: | |
print(TAG+f"use_sound= {use_sound}") | |
print(TAG+f"use_leds= {use_leds}") | |
print(TAG+f"wait_for_zero_sec= {wait_for_zero_sec}") | |
print(TAG+f"Interval set for {interval} seconds") | |
print(TAG+"Display height= {}, width= {}".format(height, width)) # result: height 127, width 295 | |
# h0 = height // 6 # 127 // 6 = 21 20 + 21 = 41 , 20 + (2 x 21) = 62, 20 + (3*21)= 83, 20 + (4x21)= 104 | |
# hlist = [h0, h0*3, h0*5] | |
hlist = [20, 41, 62, 83, 104] | |
for _ in range (len(hlist)): | |
magtag.add_text( | |
#text_font="/fonts/Arial-12.pcf", | |
text_position=( | |
10, | |
hlist[_], | |
), | |
text_scale=2, | |
) | |
# Create instances of the sensor_tmp and sensor_hum classes | |
tmp_cl = sensor_tmp(0.00, "") # create class instance with default values | |
hum_cl = sensor_hum(0.00, "") # same | |
text_items = ["Sensor data to Google", "using", "Pushingbox.com", "(c) 2024 @PaulskPt", f"USB connected: {"Yes" if on_usb else "No "}"] | |
for i in range(len(text_items)): | |
magtag.set_text(text_items[i], i, auto_refresh = False) # Display the dt, tm and tz | |
time.sleep(1) # to prevent RuntimeError Refresh too soon | |
try: | |
magtag.display.refresh() # refresh the display | |
except RuntimeError: | |
print(TAG+"RuntimeError") | |
pass # reason: Refresh too soon | |
# +-----------------------------------------------------------+ | |
# | CONNECT TO WiFi | | |
# +-----------------------------------------------------------+ | |
wifi.AuthMode.WPA2 # set only once | |
ssid = os.getenv("CIRCUITPY_WIFI_SSID") | |
print(TAG+f"Connecting to AP {os.getenv("CIRCUITPY_WIFI_SSID")}") | |
wifi_cnt = 0 | |
while not wifi_is_connected(): | |
if not do_connect(): | |
print(TAG+f"WiFi failed to connect to {ssid}") | |
wifi_cnt += 1 | |
if wifi_cnt >= 5: | |
print(TAG+f"tried {wifi_cnt} times to connect WiFi but failed. Exiting...") | |
time.sleep(3) | |
break | |
if wifi_is_connected(): | |
time.sleep(2) | |
ipv4 = ipaddress.ip_address("8.8.8.8") | |
ping_time = 0.0 | |
ping_cnt = 0 | |
while ping_time is 0.00: | |
ping_time = wifi.radio.ping(ipv4) | |
if ping_time is None: # prevent crash | |
ping_time = 0.0 | |
if ping_time < 0.001: | |
ping_cnt += 1 | |
if ping_cnt >= 10: | |
print(TAG+f"Ping to Google failed. Tried {ping_cnt} times") | |
break | |
if ping_time > 0.00: | |
print(TAG+f"Ping google.com: {ping_time} ms") | |
def blink_and_button_test(clr=None): | |
TAG= "blink_test(): " | |
if my_debug: | |
print(TAG+f"param clr= {clr} = {clr_dict[clr]}") | |
cnt = 0 | |
if clr is None: # Do the test | |
while True: | |
for i, b in enumerate(magtag.peripherals.buttons): | |
if not b.value: | |
print("Button %c pressed" % chr((ord("A") + i))) | |
magtag.peripherals.neopixel_disable = False | |
magtag.peripherals.neopixels.fill(button_colors[i]) | |
magtag.peripherals.play_tone(button_tones[i], 0.25) | |
break | |
else: | |
magtag.peripherals.neopixels.fill(button_colors[BLK]) # switch neopixels to black (off) | |
magtag.peripherals.neopixel_disable = True | |
time.sleep(0.01) | |
cnt += 1 | |
if cnt >= len(button_colors): | |
print(f"Exiting function: {TAG[:-4]}") | |
break | |
def blink_leds(clr=BLK): | |
if not use_leds: | |
return | |
TAG= "blink_leds(): " | |
if isinstance(clr, int): | |
le = len(button_colors) | |
if clr < 0: | |
clr = 0 | |
if clr >= le: | |
clr = le -1 | |
if my_debug: | |
print(TAG+f"param clr= {clr} = {clr_dict[clr]}") | |
magtag.peripherals.neopixel_disable = False | |
magtag.peripherals.neopixels.fill(button_colors[clr]) | |
if use_sound and clr != BLK: # Only sound tone if color is not black | |
magtag.peripherals.play_tone(button_tones[clr], 0.25) | |
time.sleep(0.01) | |
magtag.peripherals.neopixels.fill(button_colors[BLK]) # switch neopixels to black (off) | |
magtag.peripherals.neopixel_disable = True | |
def dt_fm_rtc(): | |
dt = time.localtime() | |
dts = "{:d}-{:02d}-{:02d}T{:02d}:{:02d}:{:02d}Z".format(dt.tm_year, dt.tm_mon, dt.tm_mday, dt.tm_hour, dt.tm_min, dt.tm_sec) | |
return dts | |
def get_time_fm_aio(): | |
global rtc_set, curr_tm, dts | |
TAG = "get_time_fm_aio(): " | |
network = magtag.network | |
TIME_URL = "https://io.adafruit.com/api/v2/{:s}/integrations/".format(os.getenv("ADAFRUIT_IO_USERNAME")) | |
TIME_URL += "time/strftime?x-aio-key={:s}".format(os.getenv("ADAFRUIT_IO_KEY")) | |
TIME_URL += "&fmt=%25Y-%25m-%25d+%25H%3A%25M%3A%25S.%25L+%25j+%25u+%25z+%25Z" | |
print(TAG+"Fetching date and time from: \"{}...\"".format(TIME_URL[:31])) # don't print aio_username neither aio_key | |
try: | |
response = network.fetch(TIME_URL) | |
except (ConnectionError, ValueError, RuntimeError) as e: | |
print(TAG+f"Error: {e}. Restarting in 3 seconds...") | |
# Exit program and restart in 3 seconds. | |
magtag.exit_and_deep_sleep(3) | |
if my_debug and response is not None: | |
print() | |
print("-" * 40) | |
print(TAG+f"response.text= {response.text}") | |
print("-" * 40) | |
if response: | |
if not rtc_set: | |
curr_date = response.text[:10] | |
curr_time = response.text[11:19] | |
print(f"curr_date: {curr_date}, curr_time: {curr_time}") | |
# tm = time.struct_time | |
tz = response.text[30:40] | |
if my_debug: | |
print(TAG+"tz= \"{}\"".format(tz)) | |
resp_lst = response.text.split(" ") # response split = ['2022-03-13', '17:02:51.303', '072', '7', '+0000', 'WET'] | |
if resp_lst[5] == 'WEST': | |
dst = 1 | |
elif resp_lst[5] == 'WET': | |
dst = 0 | |
else: | |
dst = -1 | |
if my_debug: | |
print(TAG+"dst=", dst) | |
print(TAG+"response.text.split=", resp_lst) | |
dt = response.text[:10] | |
# tm = response.text[11:16] # 23] | |
hh = int(resp_lst[1][:2]) | |
mm = int(resp_lst[1][3:5]) # +mm_corr # add the correction | |
ss = int(resp_lst[1][6:8]) | |
yd = int(resp_lst[2]) # day of the year | |
wd = int(resp_lst[3])-1 # day of the week -- strftime %u (weekday base Monday = 1), so correct because CPY datetime uses base 0 | |
# sDt = "Day of the year: {}, {} {} {} {} {}".format(yd, weekdays[wd], resp_lst[0], resp_lst[1][:5], resp_lst[4], resp_lst[5]) | |
# Set the internal RTC | |
yy = int(dt[:4]) | |
mo = int(dt[5:7]) | |
dd = int(dt[8:10]) | |
tm2 = (yy, mo, dd, hh, mm, ss, wd, yd, dst) | |
tm3 = time.struct_time(tm2) | |
if my_debug: | |
print(TAG+"dt=",dt) | |
print(TAG+"yy ={}, mo={}, dd={}".format(yy, mm, dd)) | |
print(TAG+"tm2=",tm2) | |
print(TAG+"tm3=",tm3) | |
rtc_bi.datetime = tm3 # set the built-in RTC | |
if wait_for_zero_sec: # see flag at start of this func | |
print(TAG+"Waiting for time.localtime seconds reaching 0 ...") | |
while True: | |
t = time.localtime() | |
if t[5] == 0: # Wait until seconds is almost 60 (0) | |
# print("t[tm_sec]=", t[5]) | |
break | |
print(TAG+f"finished waiting for zero second") | |
curr_tm = time.time() # get the time in seconds since epoch (set curr_tm only at startup) | |
rtc_set = True | |
# Prepare datetime for funct get_th_direct() | |
# format: 2022-08-10T16:40:16Z | |
dts = dt[:4] + "-" + dt[5:7] + "-" + dt[8:10] + "T" + resp_lst[1][:2] + ":" + resp_lst[1][3:5] + ":" + resp_lst[1][6:8] + "Z" | |
response.close() # Free resources (like socket) - to be used elsewhere | |
def get_th_direct(): | |
global t_dict, h_dict, curr_tm, tmp_old, hum_old, tmp_cl, hum_cl, sensor | |
# datetime e.g.: 2022-08-10T16:40:16Z | |
TAG = "get_th_direct(): " | |
dts = dt_fm_rtc() # get datetime from builtin rtc | |
# -------------------------------------------------------------- | |
if not sensor: | |
try: | |
sensor = adafruit_ahtx0.AHTx0(i2c) | |
except ValueError as e: | |
print(TAG+f"Error: {e}. Check wiring!") | |
if sensor: | |
try: | |
tmp = sensor.temperature | |
hum = sensor.relative_humidity | |
if my_debug: | |
blink_leds(YLW) | |
tmp_cl.tmp = tmp | |
tmp_cl.last_upd = dts | |
if tmp != tmp_old: | |
tmp_old = tmp | |
# ------------------ | |
hum_cl.hum = hum | |
hum_cl.last_upd = dts | |
if hum != hum_old: | |
hum_old = hum | |
# ----------------- | |
if my_debug: | |
print(TAG+f"updated_at: {tmp_cl.last_upd}") | |
print(TAG+f"Temperature: {tmp_cl.tmp}") | |
print(TAG+f"Humidity: {hum_cl.hum}") | |
except ValueError as e: | |
print(TAG+f"Error: {e}. Check wiring!") | |
pass | |
def pr_th_msg(): | |
global stat_result | |
TAG = "pr_th_msg(): " | |
if stat_result is None: | |
stat_result = "" | |
ret = True | |
upd_dt = tmp_cl.last_upd # [:10] # e.g.: 2022-08-10T16:40:16Z | |
# ----------------- | |
tmp = tmp_cl.tmp | |
tmp_s = str(tmp) | |
# ----------------- | |
hum = hum_cl.hum | |
hum_s = str(hum) | |
# ---------------- | |
text_items = ["latest sensor data "+stat_result, "-" * 23, upd_dt, "Temperature: "+tmp_s+" C", "Humidity: "+hum_s+" %"] | |
magtag.remove_all_text | |
for i in range(len(text_items)): | |
magtag.set_text(text_items[i], i, auto_refresh = False) # Display the dt, tm and tz | |
cnt = 0 | |
while True: | |
try: | |
magtag.display.refresh() # refresh the display | |
cnt += 1 | |
if cnt >= 10: | |
ret = False | |
break | |
except RuntimeError: | |
# print(TAG+"RuntimeError") | |
pass # reason: Refresh too soon | |
return ret | |
def send_to_pushingbox(): | |
global msg_sent, upd_dt_old, tmp_old, hum_old, stat_result | |
TAG = "send_to_pushingbox(): " | |
ret = True | |
tmp_s = None | |
hum_s = None | |
network = magtag.network | |
stat_result = None | |
devid = os.getenv("PUSHING_BOX_DEVID") # device ID on Pushingbox for our Scenario | |
upd_dt = tmp_cl.last_upd # [:10] # e.g.: 2022-08-10T16:40:16Z | |
# -------------------------------------------------------------- | |
tmp = tmp_cl.tmp | |
tmp_s = str(tmp) | |
if my_debug: | |
print(TAG+f"tmp_s= \'{tmp_s}\', tmp_old= {tmp_old}") | |
# -------------------------------------------------------------- | |
hum = hum_cl.hum | |
hum_s = str(hum) | |
if my_debug: | |
print(TAG+f"hum_s= \'{hum_s}\', hum_old= {hum_old}") | |
# -------------------------------------------------------------- | |
# le_old = len(upd_dt_old) | |
# if (le_old > 0) and (tmp == tmp_old) and (hum == hum_old): # and upd_dt == upd_dt_old | |
if (upd_dt_old == upd_dt) and (tmp == tmp_old) and (hum == hum_old): # and upd_dt == upd_dt_old | |
print(TAG+"datetime stamp unchanged. Waiting for new sensor data...") | |
return ret # We don't want to send duplicates | |
else: | |
upd_dt_old = upd_dt # | |
#upd_tm = t_dict["updated_at"][11:19] | |
msg_sent += 1 # increase the messages sent count | |
# dteData = upd_dt # Added 2024-03-22 because this variable was missing. | |
# ?date=$date$&time=$time$&temp=$temp$&hum=$hum$ | |
s = "http://api.pushingbox.com/pushingbox?devid=" | |
s += devid | |
s += "&date=\"" + upd_dt + "\"" | |
s += "&temp=" + tmp_s | |
s += "&hum=" + hum_s | |
if my_debug: | |
print(TAG+upd_dt, end='') | |
print(". Sending Data message nr: ", end='') | |
print(msg_sent, end='') | |
print(" to middle-man server...", end='\n') | |
print(TAG+"Going to send:", end='') | |
print("\n\""+s, end='') | |
print("\"", end='\n') # To complete the message to the Serial (REPL) window | |
print(TAG+"Data Sent") | |
try: | |
response = network.fetch(s) # Get the spreadsheet partly | |
except OSError as e: | |
print(TAG+f"Error: {e}") | |
if e.args[0] == -2: # gaierror | |
# See: https://docs.circuitpython.org/_/downloads/en/6.3.x/pdf/, page 216 | |
return # do nothing | |
if response: | |
le = len(response.text) | |
if le > 0: | |
n = response.text.find("404") | |
print(TAG,end='') | |
if n >=0: | |
print("error 404: file not found on this server.") | |
else: | |
print(f"response.text[:100]= {response.text[:100]}", end='') | |
print(" [...] ", end='') | |
print(f"{response.text[-100:]}", end='\n') | |
status = response.status_code | |
stat_result = "OK" if status == 200 else "NO" | |
print() | |
s1 = "response.status_code=" | |
s2 = "{} (= {})".format(status, stat_result) | |
print(TAG+f"{s1} {s2}") | |
if status == 200: | |
blink_leds(GRN) | |
else: | |
blink_leds(RED) | |
if my_debug: | |
pr_msg(["send result:", s2]) | |
response = None | |
if my_debug: | |
print(TAG+f"upd_dt= {upd_dt}, tmp_s= {tmp_s}, hum_s= {hum_s}") | |
pr_th_msg() | |
return ret | |
def yes_no(nr): | |
ret = None | |
y = "Yes" | |
n = "No " | |
if isinstance(nr, int): | |
if nr >= 0 and nr <= 3: | |
if nr == SOUND_IDX: | |
ret = y if use_sound else n | |
if nr == LEDS_IDX: | |
ret = y if use_leds else n | |
if nr == ZEROSEC_IDX: | |
ret = y if wait_for_zero_sec else n | |
if nr == DEBUG_IDX: | |
ret = y if my_debug else n | |
return ret | |
def pr_buttons(): | |
text_items = [ | |
"Btn: Function:", | |
"A: sound", | |
"B: LEDs", | |
"C: wait for zero sec", | |
"D: debug texts"] | |
pr_msg(text_items) | |
def pr_flags(): | |
TAG= "pr_flags(): " | |
itms_lst = ["sound", "LEDs", "start at zero sec", "print debug", ] | |
le = len(itms_lst) | |
print("\nStatus of global flags: (set in file settings.toml):") | |
for _ in range(le): | |
print(TAG+"{:17s}: {:s}".format(itms_lst[_], yes_no(_))) | |
print() | |
text_items = ["global flags state:"] | |
for _ in range(le): | |
s = "{:17s}: {:s}".format(itms_lst[_], yes_no(_)) | |
text_items.append(s) | |
for i in range(len(text_items)): | |
magtag.set_text(text_items[i], i, auto_refresh = False) # Display the dt, tm and tz | |
time.sleep(1) # to prevent RuntimeError Refresh too soon | |
cnt = 0 | |
while True: | |
try: | |
magtag.display.refresh() # refresh the display | |
cnt += 1 | |
if cnt >= 10: | |
break | |
except RuntimeError: | |
# print(TAG+"RuntimeError") | |
pass # reason: Refresh too soon | |
def is_usb(): | |
# Test if we're connected to USB | |
# If an error occurs we are on USB | |
ret = False | |
try: | |
from storage import remount | |
remount("/", False) | |
except (RuntimeError) as e: | |
ret = True | |
print(f"is_usb(): Are we connected to USB? {"Yes" if ret else "No"}") | |
return ret | |
def do_connect(): | |
global ip | |
TAG = "do_connect(): " | |
ret = False | |
# Get env variables from file settings.toml | |
ssid = os.getenv("CIRCUITPY_WIFI_SSID") | |
pw = os.getenv("CIRCUITPY_WIFI_PASSWORD") | |
s__ip = "" | |
try: | |
wifi.radio.connect(ssid=ssid, password=pw) | |
except ConnectionError as e: | |
print(TAG+f"WiFi connection Error: \'{e}\'") | |
except Exception as e: | |
print(TAG+f"Error: {dir(e)}") | |
ip = wifi.radio.ipv4_address | |
if ip: | |
s__ip = str(ip) | |
ret = True | |
if my_debug: | |
print(TAG+f"connected to \'{ssid}\'. IP: {s__ip}") | |
return ret | |
def wifi_is_connected(): | |
global ip | |
s__ip = str(ip) | |
return True if s__ip is not None and len(s__ip) > 0 and s__ip != '0.0.0.0' else False | |
def pr_msg(msg): | |
text_items = [] | |
le_max = 5 | |
if isinstance(msg, list): | |
le_msg = len(msg) | |
if le_msg > 0 and le_msg <= le_max: | |
for _ in range(len(msg)): | |
text_items.append(msg[_]) | |
le = len(text_items) | |
if le_max - le > 0: # fill up with blank lines | |
for _ in range(le_max - le): | |
text_items.append(" ") | |
for i in range(len(text_items)): | |
magtag.set_text(text_items[i], i, auto_refresh = False) # Display the dt, tm and tz | |
time.sleep(1) # to prevent RuntimeError Refresh too soon | |
cnt = 0 | |
while True: | |
try: | |
magtag.display.refresh() # refresh the display | |
cnt += 1 | |
if cnt >= 10: | |
break | |
except RuntimeError: | |
# print(TAG+"RuntimeError") | |
pass # reason: Refresh too soon | |
def wr_to_toml(itm): | |
TAG= "wr_to_toml(): " | |
toml_f = "settings.toml" | |
if on_usb: | |
s1 = "Writing to file" | |
s2 = "works only when" | |
s3 = "not connected to USB" | |
print(TAG+f"{s1}{toml_f} {s2} {s3}") | |
pr_msg([s1, toml_f, s2, s3]) | |
pr_th_msg() # rewrite the temperature & humidity page | |
return False | |
ret = True | |
delay = 3 | |
itms = [("WAIT_FOR_ZERO_SEC", wait_for_zero_sec), ("MY_DEBUG", my_debug)] | |
print(TAG+f"param rcvd: itm= {itm}") | |
itm_s = itms[itm][0] | |
val = itms[itm][1] | |
val_s = "1" if val == True else "0" | |
print(TAG+f"Trying to write to file: {toml_f}, item: \"{itm_s}\" with value: {val_s}") | |
# Write | |
try: | |
from cptoml import put | |
from storage import remount | |
remount("/", False) | |
#put("CIRCUITPY_PYSTACK_SIZE", 7000) # To set an item in root table | |
put(itm_s, val_s) #, "subtable1", comment="This is useless") # To set item1 in subtable1 with comment | |
remount("/", True) | |
pr_msg([itm_s, "value: " + val_s, "successfully", "written to:", toml_f]) | |
print("Software reset in %d seconds" % delay) | |
time.sleep(delay) | |
supervisor.reload() | |
except (RuntimeError, ImportError, OSError) as e: | |
print(TAG+f"Error: {e}") | |
ret = False | |
return ret | |
def main(): | |
global curr_tm, use_sound, use_leds, wait_for_zero_sec, my_debug, interval | |
TAG = 'main(): ' | |
setup() | |
curr_tm = time.time() # set curr_tm for the first time | |
start = True | |
msg_sent = False | |
delay = 3 | |
# blink_and_button_test() # Test the Magtag LEDs | |
pr_buttons() | |
pr_flags() | |
toml_zero_sec = 0 | |
toml_debug = 1 | |
wifi_cnt = 0 | |
doit = False | |
while True: | |
try: | |
while not wifi_is_connected(): | |
if do_connect(): | |
break | |
else: | |
wifi_cnt += 1 | |
if wifi_cnt >= 5: | |
print(TAG+f"WiFi connection failed. Tried {wifi_cnt} times") | |
raise RuntimeError | |
if magtag.peripherals.button_a_pressed: | |
use_sound = not use_sound # toggle sound | |
s1 = "button A pressed." | |
s2 = "sound {:s}".format(yes_no(SOUND_IDX)) | |
print(TAG+f"{s1} {s2}") | |
pr_msg([s1, s2]) | |
pr_th_msg() # rewrite the temperature & humidity page | |
if magtag.peripherals.button_b_pressed: | |
use_leds = not use_leds # toggle leds | |
s1 = "button B pressed." | |
s2 = "LEDs {:s}".format(yes_no(LEDS_IDX)) | |
print(TAG+f"{s1} {s2}") | |
pr_msg([s1, s2]) | |
pr_th_msg() # rewrite the temperature & humidity page | |
if magtag.peripherals.button_c_pressed: | |
wait_for_zero_sec = not wait_for_zero_sec | |
print(TAG+"button C pressed. Start time wait for zero seconds {:s}".format(yes_no(ZEROSEC_IDX))) | |
wr_to_toml(toml_zero_sec) | |
if magtag.peripherals.button_d_pressed: | |
my_debug = not my_debug | |
print(TAG+"button d pressed. Debug print statements {:s}".format(yes_no(DEBUG_IDX))) | |
wr_to_toml(toml_debug) | |
if not rtc_set: | |
get_time_fm_aio() | |
if rtc_set: | |
ct = time.time() # rtc_bi.datetime | |
c_diff = ct - curr_tm | |
dt1 = interval // 6 # default: 3600 seconds. 3600 // 6 = 600 seconds = 10 minutes. See setup(). | |
dt2 = interval # default: 3600 seconds = 1 hour | |
c1 = c_diff % dt1 | |
c2 = c_diff % dt2 | |
if c1 % 10 == 0: | |
if msg_sent: | |
msg_sent = False | |
# print(TAG+f"ct= {ct}, curr_tm= {curr_tm}. Difference= {ct - curr_tm} secs.") | |
# print(TAG+f"c_diff % {dt1}= {c1}. c_diff % {dt2}= {c2}. Looping...") | |
print(TAG+"c_diff % {:3d}= {:4d}, c_diff % {:4d}= {:4d}. Looping...".format(dt1, c1, dt2, c2)) | |
# doit = True if (c2 == dt2) else False | |
if c2 == 0: | |
doit = True | |
else: | |
doit = False | |
if start or (not sensor) or (doit) and (not msg_sent): | |
start = False | |
blink_leds() # switch off LEDs | |
get_th_direct() # sensor directly connected to MAGTAG board via I2C/Stemma_QT | |
if not send_to_pushingbox(): | |
raise KeyboardInterrupt | |
else: | |
msg_sent = True | |
#if c2 == 30: | |
# sys.exit() # Temporary forced end of execution | |
if c2 >= (dt2 - 10) and c2 <= dt2: # 1 hour interval (give some space) | |
get_time_fm_aio() | |
curr_tm = ct | |
time.sleep(1) | |
except ImportError: # e.g.: no module named 'platform' (in file :/lib/Adafruit_IO/Client.py, line 24) | |
pass | |
except KeyboardInterrupt: | |
raise SystemExit | |
if __name__ == '__main__': | |
main() |
/* | |
* ----------------------------------------------- | |
* Originally published by Mogsdad@Stackoverflow | |
* Modified for jarkomdityaz.appspot.com | |
* Adapted for use on an Arduino Nano RP2040 Connect. | |
* 2022-08-01 adapted for use on an Adafruit MAGTAG datetime script by @Paulskpt Github. | |
* ----------------------------------------------- | |
* | |
* GET request query: | |
* https://script.google.com/macros/s/<id>/exec/?date=$date&temp=temp&hum=hum$* | |
* | |
* Link to shared spreadsheet. Everyone with this link can edit the sheet: | |
* https://docs.google.com/spreadsheets/d/<id>/edit?usp=sharing | |
* | |
* 2024-03-24: Renamed copy of original spreadsheet. New name: "TempHumAHT20_fm_MAGTAG" | |
* https://docs.google.com/spreadsheets/d/<id>/edit#gid=0 | |
* | |
* Example to test this script: | |
* https://script.google.com/macros/s/<id>/dev/dev?date="2022-08-09T19:54:06Z"&temp=28.0878&hum=53.8874 | |
* | |
* | |
* Example with value: | |
* https://script.google.com/macros/s/<id>/exec?date="2022-08-09T19:54:06Z"&temp=28.0878&hum=53.8874 | |
* | |
* | |
* Using spreadsheet API | |
* | |
*/ | |
function doGet(e) { | |
// Example of received data string: "date=\"2022-08-09T19:54:06Z\"&temp=28.0878&hum=53.8874"; | |
Logger.log( JSON.stringify(e) ); // view parameters | |
var result = 'Ok'; // assume success | |
if (e.parameter == undefined) { | |
result = 'No Parameters'; | |
} | |
else | |
{ // Spreadsheet filename: TempHumAHT20_fm_MAGTAG | |
var id = '<spreadsheet_id>' // Spreadsheet ID | |
var sheet = SpreadsheetApp.openById(id).getActiveSheet(); | |
var newRow = sheet.getLastRow() + 1; | |
var rowData = []; | |
for (var param in e.parameter) | |
{ | |
Logger.log('In for loop, param='+param); | |
var value = stripQuotes(e.parameter[param]); | |
Logger.log(param + ':' + e.parameter[param]); | |
Logger.log("value (stripped)= "); // +value.toString); | |
Logger.log(value); | |
switch (param) | |
{ | |
case 'date': // column_A Date (updated_at) e.g.: 2022-08-09T02:05:27Z | |
rowData[0] = value; | |
break; | |
case 'temp': // column_B Temperature | |
rowData[1] = value; | |
break; | |
case 'hum': // column_C Humidity | |
rowData[2] = value; | |
break; | |
default: | |
result = "unsupported parameter"; | |
} | |
} | |
rowData.push(new Date()); // Add the datetime of execution of this macro | |
Logger.log(JSON.stringify(rowData)); | |
// Write new row below | |
var newRange = sheet.getRange(newRow, 1, 1, rowData.length); | |
newRange.setValues([rowData]); | |
} | |
// Return result of operation | |
return ContentService.createTextOutput(result); | |
} | |
/** | |
* Remove leading and trailing single or double quotes | |
*/ | |
function stripQuotes( value ) { | |
return value.replace(/^["']|['"]$/g, ""); | |
} | |
# Only used in example 2 | |
# See: https://www.epochconverter.com/ | |
# Values are for timezone Europe/Portugal | |
dst = { | |
2024:(1711846800, 1729994400), # 2024-03-31 01:00:00 / 2024-10-27 02:00:00 | |
2025:(1743296400, 1761444000), # 2025 03-30 01:00:00 / 2025-10-28 02:00:00 | |
2026:(1774746000, 1792893600), # 2026-03-29 01:00:00 / 2026-10-25 02:00:00 | |
2027:(1806195600, 1824948000), # 2027-03-28 01:00:00 / 2027-10-31 02:00:00 | |
2028:(1837645200, 1856397600), # 2028-03-26 01:00:00 / 2028-10-29 02:00:00 | |
2029:(1869094800, 1887847200), # 2029-03-25 01:00:00 / 2029-10-28 02:00:00 | |
2030:(1901149200, 1919296800), # 2030-03-31 01:00:00 / 2030-10-27 02:00:00 | |
2031:(1932598800, 1950746400), # 2031-03-30 01:00:00 / 2031-10-26 02:00:00 | |
} |
Saturday 2024-03-23 18h22 utc | |
Board: Adafruit MagTag | |
connected to STEMMA_QT connector: Adafruit AHT20 temperature & humidity sensor | |
Board flashed with: | |
Adafruit CircuitPython 9.0.0 on 2024-03-19; Adafruit MagTag with ESP32S2 | |
IDE: mu-editor V1.2.0 | |
REPL Output: | |
soft reboot | |
Auto-reload is on. Simply save files over USB to run them or enter REPL to disable. | |
code.py uitvoer: | |
setup(): Display height= 127, width= 295 | |
setup(): Connecting to AP _____________ | |
setup(): Connected to _______________ | |
setup(): My IP address is 192.168.x.xxx | |
setup(): Ping google.com: 0.014 ms | |
get_time_fm_aio(): Fetching date and time from: "https://io.adafruit.com/api/v2/..." | |
Connecting to AP ______________ | |
Retrieving data... | |
---------------------------------------- | |
get_time_fm_aio(): response.text= 2024-03-23 18:22:41.667 083 6 +0000 UTC | |
---------------------------------------- | |
curr_date: 2024-03-23, curr_time: 18:22:41 | |
get_time_fm_aio(): dst= -1 | |
get_time_fm_aio(): response.text.split= ['2024-03-23', '18:22:41.667', '083', '6', '+0000', 'UTC'] | |
get_time_fm_aio(): Waiting for time.localtime seconds reaching 0 ... | |
main(): c_diff % 300= 0. c_diff % 1800= 0. Looping... | |
get_th_direct(): updated_at: 2024-03-23T18:22:41Z | |
get_th_direct(): Temperature: 25.1592 | |
get_th_direct(): Humidity: 53.797 | |
send_to_pushingbox(): tmp_s= '25.1592', tmp= 25.1592, tmp_old= 25.1592 | |
send_to_pushingbox(): hum_s= '53.797', hum= 53.797, hum_old= 53.797 | |
send_to_pushingbox(): 2024-03-23T18:22:41Z. Sending Data message nr: 1 to middle-man server... | |
send_to_pushingbox(): Going to send: | |
"http://api.pushingbox.com/pushingbox?devid=<devid>&date="2024-03-23T18:22:41Z"&temp=25.1592&hum=53.797" | |
send_to_pushingbox(): Data Sent | |
Retrieving data... | |
send_to_pushingbox(): response.status_code= 200 (= OK) | |
main(): c_diff % 300= 10. c_diff % 1800= 10. Looping... | |
main(): c_diff % 300= 20. c_diff % 1800= 20. Looping... | |
main(): c_diff % 300= 30. c_diff % 1800= 30. Looping... | |
main(): c_diff % 300= 40. c_diff % 1800= 40. Looping... | |
main(): c_diff % 300= 50. c_diff % 1800= 50. Looping... | |
main(): c_diff % 300= 60. c_diff % 1800= 60. Looping... | |
main(): c_diff % 300= 70. c_diff % 1800= 70. Looping... | |
main(): c_diff % 300= 80. c_diff % 1800= 80. Looping... | |
main(): c_diff % 300= 90. c_diff % 1800= 90. Looping... | |
main(): c_diff % 300= 100. c_diff % 1800= 100. Looping... | |
main(): c_diff % 300= 110. c_diff % 1800= 110. Looping... | |
main(): c_diff % 300= 120. c_diff % 1800= 120. Looping... | |
main(): c_diff % 300= 130. c_diff % 1800= 130. Looping... | |
main(): c_diff % 300= 140. c_diff % 1800= 140. Looping... | |
main(): c_diff % 300= 150. c_diff % 1800= 150. Looping... | |
main(): c_diff % 300= 160. c_diff % 1800= 160. Looping... | |
main(): c_diff % 300= 170. c_diff % 1800= 170. Looping... | |
main(): c_diff % 300= 180. c_diff % 1800= 180. Looping... | |
main(): c_diff % 300= 190. c_diff % 1800= 190. Looping... | |
main(): c_diff % 300= 200. c_diff % 1800= 200. Looping... | |
main(): c_diff % 300= 210. c_diff % 1800= 210. Looping... | |
main(): c_diff % 300= 220. c_diff % 1800= 220. Looping... | |
main(): c_diff % 300= 230. c_diff % 1800= 230. Looping... | |
main(): c_diff % 300= 240. c_diff % 1800= 240. Looping... | |
main(): c_diff % 300= 250. c_diff % 1800= 250. Looping... | |
main(): c_diff % 300= 260. c_diff % 1800= 260. Looping... | |
main(): c_diff % 300= 270. c_diff % 1800= 270. Looping... | |
main(): c_diff % 300= 280. c_diff % 1800= 280. Looping... | |
main(): c_diff % 300= 290. c_diff % 1800= 290. Looping... | |
get_th_direct(): updated_at: 2024-03-23T18:27:31Z | |
get_th_direct(): Temperature: 25.0925 | |
get_th_direct(): Humidity: 53.6681 | |
send_to_pushingbox(): tmp_s= '25.0925', tmp= 25.0925, tmp_old= 25.0925 | |
send_to_pushingbox(): hum_s= '53.6681', hum= 53.6681, hum_old= 53.6681 | |
send_to_pushingbox(): 2024-03-23T18:27:31Z. Sending Data message nr: 2 to middle-man server... | |
send_to_pushingbox(): Going to send: | |
"http://api.pushingbox.com/pushingbox?devid=<devid>&date="2024-03-23T18:27:31Z"&temp=25.0925&hum=53.6681" | |
send_to_pushingbox(): Data Sent | |
Retrieving data... | |
send_to_pushingbox(): response.status_code= 200 (= OK) | |
main(): c_diff % 300= 0. c_diff % 1800= 300. Looping... | |
main(): c_diff % 300= 10. c_diff % 1800= 310. Looping... | |
main(): c_diff % 300= 20. c_diff % 1800= 320. Looping... | |
main(): c_diff % 300= 30. c_diff % 1800= 330. Looping... | |
main(): c_diff % 300= 40. c_diff % 1800= 340. Looping... | |
main(): c_diff % 300= 50. c_diff % 1800= 350. Looping... | |
main(): c_diff % 300= 60. c_diff % 1800= 360. Looping... | |
main(): c_diff % 300= 70. c_diff % 1800= 370. Looping... | |
main(): c_diff % 300= 80. c_diff % 1800= 380. Looping... | |
main(): c_diff % 300= 90. c_diff % 1800= 390. Looping... | |
main(): c_diff % 300= 100. c_diff % 1800= 400. Looping... | |
main(): c_diff % 300= 110. c_diff % 1800= 410. Looping... | |
main(): c_diff % 300= 120. c_diff % 1800= 420. Looping... | |
main(): c_diff % 300= 130. c_diff % 1800= 430. Looping... | |
main(): c_diff % 300= 140. c_diff % 1800= 440. Looping... | |
main(): c_diff % 300= 150. c_diff % 1800= 450. Looping... | |
main(): c_diff % 300= 160. c_diff % 1800= 460. Looping... | |
main(): c_diff % 300= 170. c_diff % 1800= 470. Looping... | |
main(): c_diff % 300= 180. c_diff % 1800= 480. Looping... | |
main(): c_diff % 300= 190. c_diff % 1800= 490. Looping... | |
main(): c_diff % 300= 200. c_diff % 1800= 500. Looping... | |
main(): c_diff % 300= 210. c_diff % 1800= 510. Looping... | |
main(): c_diff % 300= 220. c_diff % 1800= 520. Looping... | |
main(): c_diff % 300= 230. c_diff % 1800= 530. Looping... | |
main(): c_diff % 300= 240. c_diff % 1800= 540. Looping... | |
main(): c_diff % 300= 250. c_diff % 1800= 550. Looping... | |
main(): c_diff % 300= 260. c_diff % 1800= 560. Looping... | |
main(): c_diff % 300= 270. c_diff % 1800= 570. Looping... | |
main(): c_diff % 300= 280. c_diff % 1800= 580. Looping... | |
main(): c_diff % 300= 290. c_diff % 1800= 590. Looping... | |
get_th_direct(): updated_at: 2024-03-23T18:32:31Z | |
get_th_direct(): Temperature: 25.1354 | |
get_th_direct(): Humidity: 53.1785 | |
send_to_pushingbox(): tmp_s= '25.1354', tmp= 25.1354, tmp_old= 25.1354 | |
send_to_pushingbox(): hum_s= '53.1785', hum= 53.1785, hum_old= 53.1785 | |
send_to_pushingbox(): 2024-03-23T18:32:31Z. Sending Data message nr: 3 to middle-man server... | |
send_to_pushingbox(): Going to send: | |
"http://api.pushingbox.com/pushingbox?devid=<devid>&date="2024-03-23T18:32:31Z"&temp=25.1354&hum=53.1785" | |
send_to_pushingbox(): Data Sent | |
Retrieving data... | |
send_to_pushingbox(): response.status_code= 200 (= OK) | |
main(): c_diff % 300= 0. c_diff % 1800= 600. Looping... | |
main(): c_diff % 300= 10. c_diff % 1800= 610. Looping... | |
main(): c_diff % 300= 20. c_diff % 1800= 620. Looping... | |
main(): c_diff % 300= 30. c_diff % 1800= 630. Looping... | |
main(): c_diff % 300= 40. c_diff % 1800= 640. Looping... | |
main(): c_diff % 300= 50. c_diff % 1800= 650. Looping... | |
main(): c_diff % 300= 60. c_diff % 1800= 660. Looping... | |
main(): c_diff % 300= 70. c_diff % 1800= 670. Looping... | |
main(): c_diff % 300= 80. c_diff % 1800= 680. Looping... | |
main(): c_diff % 300= 90. c_diff % 1800= 690. Looping... | |
main(): c_diff % 300= 100. c_diff % 1800= 700. Looping... | |
main(): c_diff % 300= 110. c_diff % 1800= 710. Looping... | |
main(): c_diff % 300= 120. c_diff % 1800= 720. Looping... | |
main(): c_diff % 300= 130. c_diff % 1800= 730. Looping... | |
main(): c_diff % 300= 140. c_diff % 1800= 740. Looping... | |
main(): c_diff % 300= 150. c_diff % 1800= 750. Looping... | |
main(): c_diff % 300= 160. c_diff % 1800= 760. Looping... | |
main(): c_diff % 300= 170. c_diff % 1800= 770. Looping... | |
main(): c_diff % 300= 180. c_diff % 1800= 780. Looping... | |
main(): c_diff % 300= 190. c_diff % 1800= 790. Looping... | |
main(): c_diff % 300= 200. c_diff % 1800= 800. Looping... | |
main(): c_diff % 300= 210. c_diff % 1800= 810. Looping... | |
main(): c_diff % 300= 220. c_diff % 1800= 820. Looping... | |
main(): c_diff % 300= 230. c_diff % 1800= 830. Looping... | |
main(): c_diff % 300= 240. c_diff % 1800= 840. Looping... | |
main(): c_diff % 300= 250. c_diff % 1800= 850. Looping... | |
main(): c_diff % 300= 260. c_diff % 1800= 860. Looping... | |
main(): c_diff % 300= 270. c_diff % 1800= 870. Looping... | |
main(): c_diff % 300= 280. c_diff % 1800= 880. Looping... | |
main(): c_diff % 300= 290. c_diff % 1800= 890. Looping... | |
get_th_direct(): updated_at: 2024-03-23T18:37:31Z | |
get_th_direct(): Temperature: 25.1554 | |
get_th_direct(): Humidity: 54.6952 | |
send_to_pushingbox(): tmp_s= '25.1554', tmp= 25.1554, tmp_old= 25.1554 | |
send_to_pushingbox(): hum_s= '54.6952', hum= 54.6952, hum_old= 54.6952 | |
send_to_pushingbox(): 2024-03-23T18:37:31Z. Sending Data message nr: 4 to middle-man server... | |
send_to_pushingbox(): Going to send: | |
"http://api.pushingbox.com/pushingbox?devid=<devid>&date="2024-03-23T18:37:31Z"&temp=25.1554&hum=54.6952" | |
send_to_pushingbox(): Data Sent | |
Retrieving data... | |
send_to_pushingbox(): response.status_code= 200 (= OK) | |
main(): c_diff % 300= 0. c_diff % 1800= 900. Looping... | |
main(): c_diff % 300= 10. c_diff % 1800= 910. Looping... | |
main(): c_diff % 300= 20. c_diff % 1800= 920. Looping... | |
main(): c_diff % 300= 30. c_diff % 1800= 930. Looping... | |
main(): c_diff % 300= 40. c_diff % 1800= 940. Looping... | |
main(): c_diff % 300= 50. c_diff % 1800= 950. Looping... | |
main(): c_diff % 300= 60. c_diff % 1800= 960. Looping... | |
main(): c_diff % 300= 70. c_diff % 1800= 970. Looping... | |
main(): c_diff % 300= 80. c_diff % 1800= 980. Looping... | |
main(): c_diff % 300= 90. c_diff % 1800= 990. Looping... | |
main(): c_diff % 300= 100. c_diff % 1800= 1000. Looping... | |
main(): c_diff % 300= 110. c_diff % 1800= 1010. Looping... | |
main(): c_diff % 300= 120. c_diff % 1800= 1020. Looping... | |
main(): c_diff % 300= 130. c_diff % 1800= 1030. Looping... | |
main(): c_diff % 300= 140. c_diff % 1800= 1040. Looping... | |
main(): c_diff % 300= 150. c_diff % 1800= 1050. Looping... | |
main(): c_diff % 300= 160. c_diff % 1800= 1060. Looping... | |
main(): c_diff % 300= 170. c_diff % 1800= 1070. Looping... | |
main(): c_diff % 300= 180. c_diff % 1800= 1080. Looping... | |
main(): c_diff % 300= 190. c_diff % 1800= 1090. Looping... | |
main(): c_diff % 300= 200. c_diff % 1800= 1100. Looping... | |
main(): c_diff % 300= 210. c_diff % 1800= 1110. Looping... | |
main(): c_diff % 300= 220. c_diff % 1800= 1120. Looping... | |
main(): c_diff % 300= 230. c_diff % 1800= 1130. Looping... | |
main(): c_diff % 300= 240. c_diff % 1800= 1140. Looping... | |
main(): c_diff % 300= 250. c_diff % 1800= 1150. Looping... | |
main(): c_diff % 300= 260. c_diff % 1800= 1160. Looping... | |
main(): c_diff % 300= 270. c_diff % 1800= 1170. Looping... | |
main(): c_diff % 300= 280. c_diff % 1800= 1180. Looping... | |
main(): c_diff % 300= 290. c_diff % 1800= 1190. Looping... | |
get_th_direct(): updated_at: 2024-03-23T18:42:31Z | |
get_th_direct(): Temperature: 24.901 | |
get_th_direct(): Humidity: 53.5997 | |
send_to_pushingbox(): tmp_s= '24.901', tmp= 24.901, tmp_old= 24.901 | |
send_to_pushingbox(): hum_s= '53.5997', hum= 53.5997, hum_old= 53.5997 | |
send_to_pushingbox(): 2024-03-23T18:42:31Z. Sending Data message nr: 5 to middle-man server... | |
send_to_pushingbox(): Going to send: | |
"http://api.pushingbox.com/pushingbox?devid=<devid>&date="2024-03-23T18:42:31Z"&temp=24.901&hum=53.5997" | |
send_to_pushingbox(): Data Sent | |
Retrieving data... | |
send_to_pushingbox(): response.status_code= 200 (= OK) | |
main(): c_diff % 300= 0. c_diff % 1800= 1200. Looping... | |
main(): c_diff % 300= 10. c_diff % 1800= 1210. Looping... | |
main(): c_diff % 300= 20. c_diff % 1800= 1220. Looping... | |
main(): c_diff % 300= 30. c_diff % 1800= 1230. Looping... | |
main(): c_diff % 300= 40. c_diff % 1800= 1240. Looping... | |
main(): c_diff % 300= 50. c_diff % 1800= 1250. Looping... | |
main(): c_diff % 300= 60. c_diff % 1800= 1260. Looping... | |
main(): c_diff % 300= 70. c_diff % 1800= 1270. Looping... | |
main(): c_diff % 300= 80. c_diff % 1800= 1280. Looping... | |
main(): c_diff % 300= 90. c_diff % 1800= 1290. Looping... | |
main(): c_diff % 300= 100. c_diff % 1800= 1300. Looping... | |
main(): c_diff % 300= 110. c_diff % 1800= 1310. Looping... | |
main(): c_diff % 300= 120. c_diff % 1800= 1320. Looping... | |
main(): c_diff % 300= 130. c_diff % 1800= 1330. Looping... | |
main(): c_diff % 300= 140. c_diff % 1800= 1340. Looping... | |
main(): c_diff % 300= 150. c_diff % 1800= 1350. Looping... | |
main(): c_diff % 300= 160. c_diff % 1800= 1360. Looping... | |
main(): c_diff % 300= 170. c_diff % 1800= 1370. Looping... | |
main(): c_diff % 300= 180. c_diff % 1800= 1380. Looping... | |
main(): c_diff % 300= 190. c_diff % 1800= 1390. Looping... | |
main(): c_diff % 300= 200. c_diff % 1800= 1400. Looping... | |
main(): c_diff % 300= 210. c_diff % 1800= 1410. Looping... | |
main(): c_diff % 300= 220. c_diff % 1800= 1420. Looping... | |
main(): c_diff % 300= 230. c_diff % 1800= 1430. Looping... | |
main(): c_diff % 300= 240. c_diff % 1800= 1440. Looping... | |
main(): c_diff % 300= 250. c_diff % 1800= 1450. Looping... | |
main(): c_diff % 300= 260. c_diff % 1800= 1460. Looping... | |
main(): c_diff % 300= 270. c_diff % 1800= 1470. Looping... | |
main(): c_diff % 300= 280. c_diff % 1800= 1480. Looping... | |
main(): c_diff % 300= 290. c_diff % 1800= 1490. Looping... | |
get_th_direct(): updated_at: 2024-03-23T18:47:31Z | |
get_th_direct(): Temperature: 24.8535 | |
get_th_direct(): Humidity: 53.9628 | |
send_to_pushingbox(): tmp_s= '24.8535', tmp= 24.8535, tmp_old= 24.8535 | |
send_to_pushingbox(): hum_s= '53.9628', hum= 53.9628, hum_old= 53.9628 | |
send_to_pushingbox(): 2024-03-23T18:47:31Z. Sending Data message nr: 6 to middle-man server... | |
send_to_pushingbox(): Going to send: | |
"http://api.pushingbox.com/pushingbox?devid=<devid>&date="2024-03-23T18:47:31Z"&temp=24.8535&hum=53.9628" | |
send_to_pushingbox(): Data Sent | |
Retrieving data... | |
send_to_pushingbox(): response.status_code= 200 (= OK) | |
main(): c_diff % 300= 0. c_diff % 1800= 1500. Looping... | |
main(): c_diff % 300= 10. c_diff % 1800= 1510. Looping... | |
main(): c_diff % 300= 20. c_diff % 1800= 1520. Looping... | |
main(): c_diff % 300= 30. c_diff % 1800= 1530. Looping... | |
main(): c_diff % 300= 40. c_diff % 1800= 1540. Looping... | |
main(): c_diff % 300= 50. c_diff % 1800= 1550. Looping... | |
main(): c_diff % 300= 60. c_diff % 1800= 1560. Looping... | |
main(): c_diff % 300= 70. c_diff % 1800= 1570. Looping... | |
main(): c_diff % 300= 80. c_diff % 1800= 1580. Looping... | |
main(): c_diff % 300= 90. c_diff % 1800= 1590. Looping... | |
main(): c_diff % 300= 100. c_diff % 1800= 1600. Looping... | |
main(): c_diff % 300= 110. c_diff % 1800= 1610. Looping... | |
main(): c_diff % 300= 120. c_diff % 1800= 1620. Looping... | |
main(): c_diff % 300= 130. c_diff % 1800= 1630. Looping... | |
main(): c_diff % 300= 140. c_diff % 1800= 1640. Looping... | |
main(): c_diff % 300= 150. c_diff % 1800= 1650. Looping... | |
main(): c_diff % 300= 160. c_diff % 1800= 1660. Looping... | |
main(): c_diff % 300= 170. c_diff % 1800= 1670. Looping... | |
main(): c_diff % 300= 180. c_diff % 1800= 1680. Looping... | |
main(): c_diff % 300= 190. c_diff % 1800= 1690. Looping... | |
main(): c_diff % 300= 200. c_diff % 1800= 1700. Looping... | |
main(): c_diff % 300= 210. c_diff % 1800= 1710. Looping... | |
main(): c_diff % 300= 220. c_diff % 1800= 1720. Looping... | |
main(): c_diff % 300= 230. c_diff % 1800= 1730. Looping... | |
main(): c_diff % 300= 240. c_diff % 1800= 1740. Looping... | |
main(): c_diff % 300= 250. c_diff % 1800= 1750. Looping... | |
main(): c_diff % 300= 260. c_diff % 1800= 1760. Looping... | |
main(): c_diff % 300= 270. c_diff % 1800= 1770. Looping... | |
main(): c_diff % 300= 280. c_diff % 1800= 1780. Looping... | |
main(): c_diff % 300= 290. c_diff % 1800= 1790. Looping... | |
get_th_direct(): updated_at: 2024-03-23T18:52:31Z | |
get_th_direct(): Temperature: 24.925 | |
get_th_direct(): Humidity: 53.6928 | |
send_to_pushingbox(): tmp_s= '24.925', tmp= 24.925, tmp_old= 24.925 | |
send_to_pushingbox(): hum_s= '53.6928', hum= 53.6928, hum_old= 53.6928 | |
send_to_pushingbox(): 2024-03-23T18:52:31Z. Sending Data message nr: 7 to middle-man server... | |
send_to_pushingbox(): Going to send: | |
"http://api.pushingbox.com/pushingbox?devid=<devid>&date="2024-03-23T18:52:31Z"&temp=24.925&hum=53.6928" | |
send_to_pushingbox(): Data Sent | |
Retrieving data... | |
send_to_pushingbox(): response.status_code= 200 (= OK) | |
get_time_fm_aio(): Fetching date and time from: "https://io.adafruit.com/api/v2/..." | |
Retrieving data... | |
---------------------------------------- | |
get_time_fm_aio(): response.text= 2024-03-23 18:52:36.342 083 6 +0000 UTC | |
---------------------------------------- | |
main(): c_diff % 300= 10. c_diff % 1800= 10. Looping... | |
main(): c_diff % 300= 20. c_diff % 1800= 20. Looping... | |
main(): c_diff % 300= 30. c_diff % 1800= 30. Looping... |
Monday 2024-04-01 00h18 utc+1 | |
Board: MAGTAG | |
soft reboot | |
Auto-reload is on. Simply save files over USB to run them or enter REPL to disable. | |
code.py output: | |
is_usb(): Are we connected to USB? Yes | |
setup(): Interval set for 3600 seconds | |
setup(): Display height= 127, width= 295 | |
setup(): Connecting to AP ____________ | |
setup(): Ping google.com: 0.013 ms | |
setup(): We have NTP | |
setup(): We have an internal RTC | |
setup(): Going to set internal RTC | |
is_dst(): dst_start_end: (1711846800, 1729994400) | |
is_dst(): dst_org 0, dst_new: 1. We are going to set the ntp object with timezone offset: 1 hour(s) | |
set_INT_RTC(): Internal (SYS) RTC is set from NTP service datetime stamp: | |
set_INT_RTC(): 4/01/2024 | |
set_INT_RTC(): 00:18:26 weekday: Monday | |
set_INT_RTC(): Note that NTP weekday starts with 0 | |
is_dst(): Are we in daylight saving time for country: 'PRT', state: '' ? Yes | |
is_dst(): Days to start of daylight saving time period: -1 | |
is_dst(): Days to end of daylight saving time period: 209 | |
Status of global flags: (set in file settings.toml): | |
pr_flags(): sound : Yes | |
pr_flags(): LEDs : Yes | |
pr_flags(): start at zero sec: No | |
pr_flags(): print debug : No | |
dt_fm_rtc(): dts= 2024-04-01T00:18:41Z | |
Connecting to AP ______________ | |
Retrieving data... | |
send_to_pushingbox(): response.status_code= 200 (= OK) | |
main(): c_diff % 600= 30. c_diff % 3600= 30. Looping... | |
main(): c_diff % 600= 40. c_diff % 3600= 40. Looping... | |
main(): c_diff % 600= 50. c_diff % 3600= 50. Looping... | |
main(): c_diff % 600= 60. c_diff % 3600= 60. Looping... | |
main(): c_diff % 600= 70. c_diff % 3600= 70. Looping... | |
main(): c_diff % 600= 80. c_diff % 3600= 80. Looping... | |
main(): c_diff % 600= 90. c_diff % 3600= 90. Looping... | |
main(): c_diff % 600= 100. c_diff % 3600= 100. Looping... | |
main(): c_diff % 600= 110. c_diff % 3600= 110. Looping... | |
main(): c_diff % 600= 120. c_diff % 3600= 120. Looping... | |
main(): c_diff % 600= 130. c_diff % 3600= 130. Looping... | |
main(): c_diff % 600= 140. c_diff % 3600= 140. Looping... | |
main(): c_diff % 600= 150. c_diff % 3600= 150. Looping... | |
main(): c_diff % 600= 160. c_diff % 3600= 160. Looping... | |
main(): c_diff % 600= 170. c_diff % 3600= 170. Looping... | |
main(): c_diff % 600= 180. c_diff % 3600= 180. Looping... | |
main(): c_diff % 600= 190. c_diff % 3600= 190. Looping... | |
main(): c_diff % 600= 200. c_diff % 3600= 200. Looping... | |
main(): c_diff % 600= 210. c_diff % 3600= 210. Looping... | |
main(): c_diff % 600= 220. c_diff % 3600= 220. Looping... | |
main(): c_diff % 600= 230. c_diff % 3600= 230. Looping... | |
main(): c_diff % 600= 240. c_diff % 3600= 240. Looping... | |
main(): c_diff % 600= 250. c_diff % 3600= 250. Looping... | |
main(): c_diff % 600= 260. c_diff % 3600= 260. Looping... | |
main(): c_diff % 600= 270. c_diff % 3600= 270. Looping... | |
main(): c_diff % 600= 280. c_diff % 3600= 280. Looping... | |
main(): c_diff % 600= 290. c_diff % 3600= 290. Looping... | |
main(): c_diff % 600= 300. c_diff % 3600= 300. Looping... | |
main(): c_diff % 600= 310. c_diff % 3600= 310. Looping... | |
main(): c_diff % 600= 320. c_diff % 3600= 320. Looping... | |
main(): c_diff % 600= 330. c_diff % 3600= 330. Looping... | |
main(): c_diff % 600= 340. c_diff % 3600= 340. Looping... | |
main(): c_diff % 600= 350. c_diff % 3600= 350. Looping... | |
main(): c_diff % 600= 360. c_diff % 3600= 360. Looping... | |
main(): c_diff % 600= 370. c_diff % 3600= 370. Looping... | |
main(): c_diff % 600= 380. c_diff % 3600= 380. Looping... | |
main(): c_diff % 600= 390. c_diff % 3600= 390. Looping... | |
main(): c_diff % 600= 400. c_diff % 3600= 400. Looping... | |
main(): c_diff % 600= 410. c_diff % 3600= 410. Looping... | |
main(): c_diff % 600= 420. c_diff % 3600= 420. Looping... | |
main(): c_diff % 600= 430. c_diff % 3600= 430. Looping... | |
main(): c_diff % 600= 440. c_diff % 3600= 440. Looping... | |
main(): c_diff % 600= 450. c_diff % 3600= 450. Looping... | |
main(): c_diff % 600= 460. c_diff % 3600= 460. Looping... | |
main(): c_diff % 600= 470. c_diff % 3600= 470. Looping... | |
main(): c_diff % 600= 480. c_diff % 3600= 480. Looping... | |
main(): c_diff % 600= 490. c_diff % 3600= 490. Looping... | |
main(): c_diff % 600= 500. c_diff % 3600= 500. Looping... | |
main(): c_diff % 600= 510. c_diff % 3600= 510. Looping... | |
main(): c_diff % 600= 520. c_diff % 3600= 520. Looping... | |
main(): c_diff % 600= 530. c_diff % 3600= 530. Looping... | |
main(): c_diff % 600= 540. c_diff % 3600= 540. Looping... | |
main(): c_diff % 600= 550. c_diff % 3600= 550. Looping... | |
main(): c_diff % 600= 560. c_diff % 3600= 560. Looping... | |
main(): c_diff % 600= 570. c_diff % 3600= 570. Looping... | |
main(): c_diff % 600= 580. c_diff % 3600= 580. Looping... | |
main(): c_diff % 600= 590. c_diff % 3600= 590. Looping... | |
main(): c_diff % 600= 0. c_diff % 3600= 600. Looping... | |
main(): c_diff % 600= 10. c_diff % 3600= 610. Looping... | |
main(): c_diff % 600= 20. c_diff % 3600= 620. Looping... | |
main(): c_diff % 600= 30. c_diff % 3600= 630. Looping... | |
main(): c_diff % 600= 40. c_diff % 3600= 640. Looping... | |
main(): c_diff % 600= 50. c_diff % 3600= 650. Looping... | |
main(): c_diff % 600= 60. c_diff % 3600= 660. Looping... | |
main(): c_diff % 600= 70. c_diff % 3600= 670. Looping... | |
main(): c_diff % 600= 80. c_diff % 3600= 680. Looping... | |
main(): c_diff % 600= 90. c_diff % 3600= 690. Looping... | |
main(): c_diff % 600= 100. c_diff % 3600= 700. Looping... | |
main(): c_diff % 600= 110. c_diff % 3600= 710. Looping... | |
main(): c_diff % 600= 120. c_diff % 3600= 720. Looping... | |
main(): c_diff % 600= 130. c_diff % 3600= 730. Looping... | |
main(): c_diff % 600= 140. c_diff % 3600= 740. Looping... | |
main(): c_diff % 600= 150. c_diff % 3600= 750. Looping... | |
main(): c_diff % 600= 160. c_diff % 3600= 760. Looping... | |
main(): c_diff % 600= 170. c_diff % 3600= 770. Looping... | |
main(): c_diff % 600= 180. c_diff % 3600= 780. Looping... | |
main(): c_diff % 600= 190. c_diff % 3600= 790. Looping... | |
main(): c_diff % 600= 200. c_diff % 3600= 800. Looping... | |
main(): c_diff % 600= 210. c_diff % 3600= 810. Looping... | |
main(): c_diff % 600= 220. c_diff % 3600= 820. Looping... | |
main(): c_diff % 600= 230. c_diff % 3600= 830. Looping... | |
main(): c_diff % 600= 240. c_diff % 3600= 840. Looping... | |
main(): c_diff % 600= 250. c_diff % 3600= 850. Looping... | |
main(): c_diff % 600= 260. c_diff % 3600= 860. Looping... | |
main(): c_diff % 600= 270. c_diff % 3600= 870. Looping... | |
main(): c_diff % 600= 280. c_diff % 3600= 880. Looping... | |
main(): c_diff % 600= 290. c_diff % 3600= 890. Looping... | |
main(): c_diff % 600= 300. c_diff % 3600= 900. Looping... | |
main(): c_diff % 600= 310. c_diff % 3600= 910. Looping... | |
main(): c_diff % 600= 320. c_diff % 3600= 920. Looping... | |
main(): c_diff % 600= 330. c_diff % 3600= 930. Looping... | |
main(): c_diff % 600= 340. c_diff % 3600= 940. Looping... | |
main(): c_diff % 600= 350. c_diff % 3600= 950. Looping... | |
main(): c_diff % 600= 360. c_diff % 3600= 960. Looping... | |
main(): c_diff % 600= 370. c_diff % 3600= 970. Looping... | |
main(): c_diff % 600= 380. c_diff % 3600= 980. Looping... | |
main(): c_diff % 600= 390. c_diff % 3600= 990. Looping... | |
main(): c_diff % 600= 400. c_diff % 3600= 1000. Looping... | |
main(): c_diff % 600= 410. c_diff % 3600= 1010. Looping... | |
main(): c_diff % 600= 420. c_diff % 3600= 1020. Looping... | |
main(): c_diff % 600= 430. c_diff % 3600= 1030. Looping... | |
main(): c_diff % 600= 440. c_diff % 3600= 1040. Looping... | |
main(): c_diff % 600= 450. c_diff % 3600= 1050. Looping... | |
main(): c_diff % 600= 460. c_diff % 3600= 1060. Looping... | |
main(): c_diff % 600= 470. c_diff % 3600= 1070. Looping... | |
main(): c_diff % 600= 480. c_diff % 3600= 1080. Looping... | |
main(): c_diff % 600= 490. c_diff % 3600= 1090. Looping... | |
main(): c_diff % 600= 500. c_diff % 3600= 1100. Looping... | |
main(): c_diff % 600= 510. c_diff % 3600= 1110. Looping... | |
main(): c_diff % 600= 520. c_diff % 3600= 1120. Looping... | |
main(): c_diff % 600= 530. c_diff % 3600= 1130. Looping... | |
main(): c_diff % 600= 540. c_diff % 3600= 1140. Looping... | |
main(): c_diff % 600= 550. c_diff % 3600= 1150. Looping... | |
main(): c_diff % 600= 560. c_diff % 3600= 1160. Looping... | |
main(): c_diff % 600= 570. c_diff % 3600= 1170. Looping... | |
main(): c_diff % 600= 580. c_diff % 3600= 1180. Looping... | |
main(): c_diff % 600= 590. c_diff % 3600= 1190. Looping... | |
main(): c_diff % 600= 0. c_diff % 3600= 1200. Looping... | |
main(): c_diff % 600= 10. c_diff % 3600= 1210. Looping... | |
main(): c_diff % 600= 20. c_diff % 3600= 1220. Looping... | |
main(): c_diff % 600= 30. c_diff % 3600= 1230. Looping... | |
main(): c_diff % 600= 40. c_diff % 3600= 1240. Looping... | |
main(): c_diff % 600= 50. c_diff % 3600= 1250. Looping... | |
main(): c_diff % 600= 60. c_diff % 3600= 1260. Looping... | |
main(): c_diff % 600= 70. c_diff % 3600= 1270. Looping... | |
main(): c_diff % 600= 80. c_diff % 3600= 1280. Looping... | |
main(): c_diff % 600= 90. c_diff % 3600= 1290. Looping... | |
main(): c_diff % 600= 100. c_diff % 3600= 1300. Looping... | |
main(): c_diff % 600= 110. c_diff % 3600= 1310. Looping... | |
main(): c_diff % 600= 120. c_diff % 3600= 1320. Looping... | |
main(): c_diff % 600= 130. c_diff % 3600= 1330. Looping... | |
main(): c_diff % 600= 140. c_diff % 3600= 1340. Looping... | |
main(): c_diff % 600= 150. c_diff % 3600= 1350. Looping... | |
main(): c_diff % 600= 160. c_diff % 3600= 1360. Looping... | |
main(): c_diff % 600= 170. c_diff % 3600= 1370. Looping... | |
main(): c_diff % 600= 180. c_diff % 3600= 1380. Looping... | |
main(): c_diff % 600= 190. c_diff % 3600= 1390. Looping... | |
main(): c_diff % 600= 200. c_diff % 3600= 1400. Looping... | |
main(): c_diff % 600= 210. c_diff % 3600= 1410. Looping... | |
main(): c_diff % 600= 220. c_diff % 3600= 1420. Looping... | |
main(): c_diff % 600= 230. c_diff % 3600= 1430. Looping... | |
main(): c_diff % 600= 240. c_diff % 3600= 1440. Looping... | |
main(): c_diff % 600= 250. c_diff % 3600= 1450. Looping... | |
main(): c_diff % 600= 260. c_diff % 3600= 1460. Looping... | |
main(): c_diff % 600= 270. c_diff % 3600= 1470. Looping... | |
main(): c_diff % 600= 280. c_diff % 3600= 1480. Looping... | |
main(): c_diff % 600= 290. c_diff % 3600= 1490. Looping... | |
main(): c_diff % 600= 300. c_diff % 3600= 1500. Looping... | |
main(): c_diff % 600= 310. c_diff % 3600= 1510. Looping... | |
main(): c_diff % 600= 320. c_diff % 3600= 1520. Looping... | |
main(): c_diff % 600= 330. c_diff % 3600= 1530. Looping... | |
main(): c_diff % 600= 340. c_diff % 3600= 1540. Looping... | |
main(): c_diff % 600= 350. c_diff % 3600= 1550. Looping... | |
main(): c_diff % 600= 360. c_diff % 3600= 1560. Looping... | |
main(): c_diff % 600= 370. c_diff % 3600= 1570. Looping... | |
main(): c_diff % 600= 380. c_diff % 3600= 1580. Looping... | |
main(): c_diff % 600= 390. c_diff % 3600= 1590. Looping... | |
main(): c_diff % 600= 400. c_diff % 3600= 1600. Looping... | |
main(): c_diff % 600= 410. c_diff % 3600= 1610. Looping... | |
main(): c_diff % 600= 420. c_diff % 3600= 1620. Looping... | |
main(): c_diff % 600= 430. c_diff % 3600= 1630. Looping... | |
main(): c_diff % 600= 440. c_diff % 3600= 1640. Looping... | |
main(): c_diff % 600= 450. c_diff % 3600= 1650. Looping... | |
main(): c_diff % 600= 460. c_diff % 3600= 1660. Looping... | |
main(): c_diff % 600= 470. c_diff % 3600= 1670. Looping... | |
main(): c_diff % 600= 480. c_diff % 3600= 1680. Looping... | |
main(): c_diff % 600= 490. c_diff % 3600= 1690. Looping... | |
main(): c_diff % 600= 500. c_diff % 3600= 1700. Looping... | |
main(): c_diff % 600= 510. c_diff % 3600= 1710. Looping... | |
main(): c_diff % 600= 520. c_diff % 3600= 1720. Looping... | |
main(): c_diff % 600= 530. c_diff % 3600= 1730. Looping... | |
main(): c_diff % 600= 540. c_diff % 3600= 1740. Looping... | |
main(): c_diff % 600= 550. c_diff % 3600= 1750. Looping... | |
main(): c_diff % 600= 560. c_diff % 3600= 1760. Looping... | |
main(): c_diff % 600= 570. c_diff % 3600= 1770. Looping... | |
main(): c_diff % 600= 580. c_diff % 3600= 1780. Looping... | |
main(): c_diff % 600= 590. c_diff % 3600= 1790. Looping... | |
main(): c_diff % 600= 0. c_diff % 3600= 1800. Looping... | |
main(): c_diff % 600= 10. c_diff % 3600= 1810. Looping... | |
main(): c_diff % 600= 20. c_diff % 3600= 1820. Looping... | |
main(): c_diff % 600= 30. c_diff % 3600= 1830. Looping... | |
main(): c_diff % 600= 40. c_diff % 3600= 1840. Looping... | |
main(): c_diff % 600= 50. c_diff % 3600= 1850. Looping... | |
main(): c_diff % 600= 60. c_diff % 3600= 1860. Looping... | |
main(): c_diff % 600= 70. c_diff % 3600= 1870. Looping... | |
main(): c_diff % 600= 80. c_diff % 3600= 1880. Looping... | |
main(): c_diff % 600= 90. c_diff % 3600= 1890. Looping... | |
main(): c_diff % 600= 100. c_diff % 3600= 1900. Looping... | |
main(): c_diff % 600= 110. c_diff % 3600= 1910. Looping... | |
main(): c_diff % 600= 120. c_diff % 3600= 1920. Looping... | |
main(): c_diff % 600= 130. c_diff % 3600= 1930. Looping... | |
main(): c_diff % 600= 140. c_diff % 3600= 1940. Looping... | |
main(): c_diff % 600= 150. c_diff % 3600= 1950. Looping... | |
main(): c_diff % 600= 160. c_diff % 3600= 1960. Looping... | |
main(): c_diff % 600= 170. c_diff % 3600= 1970. Looping... | |
main(): c_diff % 600= 180. c_diff % 3600= 1980. Looping... | |
main(): c_diff % 600= 190. c_diff % 3600= 1990. Looping... | |
main(): c_diff % 600= 200. c_diff % 3600= 2000. Looping... | |
main(): c_diff % 600= 210. c_diff % 3600= 2010. Looping... | |
main(): c_diff % 600= 220. c_diff % 3600= 2020. Looping... | |
main(): c_diff % 600= 230. c_diff % 3600= 2030. Looping... | |
main(): c_diff % 600= 240. c_diff % 3600= 2040. Looping... | |
main(): c_diff % 600= 250. c_diff % 3600= 2050. Looping... | |
main(): c_diff % 600= 260. c_diff % 3600= 2060. Looping... | |
main(): c_diff % 600= 270. c_diff % 3600= 2070. Looping... | |
main(): c_diff % 600= 280. c_diff % 3600= 2080. Looping... | |
main(): c_diff % 600= 290. c_diff % 3600= 2090. Looping... | |
main(): c_diff % 600= 300. c_diff % 3600= 2100. Looping... | |
main(): c_diff % 600= 310. c_diff % 3600= 2110. Looping... | |
main(): c_diff % 600= 320. c_diff % 3600= 2120. Looping... | |
main(): c_diff % 600= 330. c_diff % 3600= 2130. Looping... | |
main(): c_diff % 600= 340. c_diff % 3600= 2140. Looping... | |
main(): c_diff % 600= 350. c_diff % 3600= 2150. Looping... | |
main(): c_diff % 600= 360. c_diff % 3600= 2160. Looping... | |
main(): c_diff % 600= 370. c_diff % 3600= 2170. Looping... | |
main(): c_diff % 600= 380. c_diff % 3600= 2180. Looping... | |
main(): c_diff % 600= 390. c_diff % 3600= 2190. Looping... | |
main(): c_diff % 600= 400. c_diff % 3600= 2200. Looping... | |
main(): c_diff % 600= 410. c_diff % 3600= 2210. Looping... | |
main(): c_diff % 600= 420. c_diff % 3600= 2220. Looping... | |
main(): c_diff % 600= 430. c_diff % 3600= 2230. Looping... | |
main(): c_diff % 600= 440. c_diff % 3600= 2240. Looping... | |
main(): c_diff % 600= 450. c_diff % 3600= 2250. Looping... | |
main(): c_diff % 600= 460. c_diff % 3600= 2260. Looping... | |
main(): c_diff % 600= 470. c_diff % 3600= 2270. Looping... | |
main(): c_diff % 600= 480. c_diff % 3600= 2280. Looping... | |
main(): c_diff % 600= 490. c_diff % 3600= 2290. Looping... | |
main(): c_diff % 600= 500. c_diff % 3600= 2300. Looping... | |
main(): c_diff % 600= 510. c_diff % 3600= 2310. Looping... | |
main(): c_diff % 600= 520. c_diff % 3600= 2320. Looping... | |
main(): c_diff % 600= 530. c_diff % 3600= 2330. Looping... | |
main(): c_diff % 600= 540. c_diff % 3600= 2340. Looping... | |
main(): c_diff % 600= 550. c_diff % 3600= 2350. Looping... | |
main(): c_diff % 600= 560. c_diff % 3600= 2360. Looping... | |
main(): c_diff % 600= 570. c_diff % 3600= 2370. Looping... | |
main(): c_diff % 600= 580. c_diff % 3600= 2380. Looping... | |
main(): c_diff % 600= 590. c_diff % 3600= 2390. Looping... | |
main(): c_diff % 600= 0. c_diff % 3600= 2400. Looping... | |
main(): c_diff % 600= 10. c_diff % 3600= 2410. Looping... | |
main(): c_diff % 600= 20. c_diff % 3600= 2420. Looping... | |
main(): c_diff % 600= 30. c_diff % 3600= 2430. Looping... | |
main(): c_diff % 600= 40. c_diff % 3600= 2440. Looping... | |
main(): c_diff % 600= 50. c_diff % 3600= 2450. Looping... | |
main(): c_diff % 600= 60. c_diff % 3600= 2460. Looping... | |
main(): c_diff % 600= 70. c_diff % 3600= 2470. Looping... | |
main(): c_diff % 600= 80. c_diff % 3600= 2480. Looping... | |
main(): c_diff % 600= 90. c_diff % 3600= 2490. Looping... | |
main(): c_diff % 600= 100. c_diff % 3600= 2500. Looping... | |
main(): c_diff % 600= 110. c_diff % 3600= 2510. Looping... | |
main(): c_diff % 600= 120. c_diff % 3600= 2520. Looping... | |
main(): c_diff % 600= 130. c_diff % 3600= 2530. Looping... | |
main(): c_diff % 600= 140. c_diff % 3600= 2540. Looping... | |
main(): c_diff % 600= 150. c_diff % 3600= 2550. Looping... | |
main(): c_diff % 600= 160. c_diff % 3600= 2560. Looping... | |
main(): c_diff % 600= 170. c_diff % 3600= 2570. Looping... | |
main(): c_diff % 600= 180. c_diff % 3600= 2580. Looping... | |
main(): c_diff % 600= 190. c_diff % 3600= 2590. Looping... | |
main(): c_diff % 600= 200. c_diff % 3600= 2600. Looping... | |
main(): c_diff % 600= 210. c_diff % 3600= 2610. Looping... | |
main(): c_diff % 600= 220. c_diff % 3600= 2620. Looping... | |
main(): c_diff % 600= 230. c_diff % 3600= 2630. Looping... | |
main(): c_diff % 600= 240. c_diff % 3600= 2640. Looping... | |
main(): c_diff % 600= 250. c_diff % 3600= 2650. Looping... | |
main(): c_diff % 600= 260. c_diff % 3600= 2660. Looping... | |
main(): c_diff % 600= 270. c_diff % 3600= 2670. Looping... | |
main(): c_diff % 600= 280. c_diff % 3600= 2680. Looping... | |
main(): c_diff % 600= 290. c_diff % 3600= 2690. Looping... | |
main(): c_diff % 600= 300. c_diff % 3600= 2700. Looping... | |
main(): c_diff % 600= 310. c_diff % 3600= 2710. Looping... | |
main(): c_diff % 600= 320. c_diff % 3600= 2720. Looping... | |
main(): c_diff % 600= 330. c_diff % 3600= 2730. Looping... | |
main(): c_diff % 600= 340. c_diff % 3600= 2740. Looping... | |
main(): c_diff % 600= 350. c_diff % 3600= 2750. Looping... | |
main(): c_diff % 600= 360. c_diff % 3600= 2760. Looping... | |
main(): c_diff % 600= 370. c_diff % 3600= 2770. Looping... | |
main(): c_diff % 600= 380. c_diff % 3600= 2780. Looping... | |
main(): c_diff % 600= 390. c_diff % 3600= 2790. Looping... | |
main(): c_diff % 600= 400. c_diff % 3600= 2800. Looping... | |
main(): c_diff % 600= 410. c_diff % 3600= 2810. Looping... | |
main(): c_diff % 600= 420. c_diff % 3600= 2820. Looping... | |
main(): c_diff % 600= 430. c_diff % 3600= 2830. Looping... | |
main(): c_diff % 600= 440. c_diff % 3600= 2840. Looping... | |
main(): c_diff % 600= 450. c_diff % 3600= 2850. Looping... | |
main(): c_diff % 600= 460. c_diff % 3600= 2860. Looping... | |
main(): c_diff % 600= 470. c_diff % 3600= 2870. Looping... | |
main(): c_diff % 600= 480. c_diff % 3600= 2880. Looping... | |
main(): c_diff % 600= 490. c_diff % 3600= 2890. Looping... | |
main(): c_diff % 600= 500. c_diff % 3600= 2900. Looping... | |
main(): c_diff % 600= 510. c_diff % 3600= 2910. Looping... | |
main(): c_diff % 600= 520. c_diff % 3600= 2920. Looping... | |
main(): c_diff % 600= 530. c_diff % 3600= 2930. Looping... | |
main(): c_diff % 600= 540. c_diff % 3600= 2940. Looping... | |
main(): c_diff % 600= 550. c_diff % 3600= 2950. Looping... | |
main(): c_diff % 600= 560. c_diff % 3600= 2960. Looping... | |
main(): c_diff % 600= 570. c_diff % 3600= 2970. Looping... | |
main(): c_diff % 600= 580. c_diff % 3600= 2980. Looping... | |
main(): c_diff % 600= 590. c_diff % 3600= 2990. Looping... | |
main(): c_diff % 600= 0. c_diff % 3600= 3000. Looping... | |
main(): c_diff % 600= 10. c_diff % 3600= 3010. Looping... | |
main(): c_diff % 600= 20. c_diff % 3600= 3020. Looping... | |
main(): c_diff % 600= 30. c_diff % 3600= 3030. Looping... | |
main(): c_diff % 600= 40. c_diff % 3600= 3040. Looping... | |
main(): c_diff % 600= 50. c_diff % 3600= 3050. Looping... | |
main(): c_diff % 600= 60. c_diff % 3600= 3060. Looping... | |
main(): c_diff % 600= 70. c_diff % 3600= 3070. Looping... | |
main(): c_diff % 600= 80. c_diff % 3600= 3080. Looping... | |
main(): c_diff % 600= 90. c_diff % 3600= 3090. Looping... | |
main(): c_diff % 600= 100. c_diff % 3600= 3100. Looping... | |
main(): c_diff % 600= 110. c_diff % 3600= 3110. Looping... | |
main(): c_diff % 600= 120. c_diff % 3600= 3120. Looping... | |
main(): c_diff % 600= 130. c_diff % 3600= 3130. Looping... | |
main(): c_diff % 600= 140. c_diff % 3600= 3140. Looping... | |
main(): c_diff % 600= 150. c_diff % 3600= 3150. Looping... | |
main(): c_diff % 600= 160. c_diff % 3600= 3160. Looping... | |
main(): c_diff % 600= 170. c_diff % 3600= 3170. Looping... | |
main(): c_diff % 600= 180. c_diff % 3600= 3180. Looping... | |
main(): c_diff % 600= 190. c_diff % 3600= 3190. Looping... | |
main(): c_diff % 600= 200. c_diff % 3600= 3200. Looping... | |
main(): c_diff % 600= 210. c_diff % 3600= 3210. Looping... | |
main(): c_diff % 600= 220. c_diff % 3600= 3220. Looping... | |
main(): c_diff % 600= 230. c_diff % 3600= 3230. Looping... | |
main(): c_diff % 600= 240. c_diff % 3600= 3240. Looping... | |
main(): c_diff % 600= 250. c_diff % 3600= 3250. Looping... | |
main(): c_diff % 600= 260. c_diff % 3600= 3260. Looping... | |
main(): c_diff % 600= 270. c_diff % 3600= 3270. Looping... | |
main(): c_diff % 600= 280. c_diff % 3600= 3280. Looping... | |
main(): c_diff % 600= 290. c_diff % 3600= 3290. Looping... | |
main(): c_diff % 600= 300. c_diff % 3600= 3300. Looping... | |
main(): c_diff % 600= 310. c_diff % 3600= 3310. Looping... | |
main(): c_diff % 600= 320. c_diff % 3600= 3320. Looping... | |
main(): c_diff % 600= 330. c_diff % 3600= 3330. Looping... | |
main(): c_diff % 600= 340. c_diff % 3600= 3340. Looping... | |
main(): c_diff % 600= 350. c_diff % 3600= 3350. Looping... | |
main(): c_diff % 600= 360. c_diff % 3600= 3360. Looping... | |
main(): c_diff % 600= 370. c_diff % 3600= 3370. Looping... | |
main(): c_diff % 600= 380. c_diff % 3600= 3380. Looping... | |
main(): c_diff % 600= 390. c_diff % 3600= 3390. Looping... | |
main(): c_diff % 600= 400. c_diff % 3600= 3400. Looping... | |
main(): c_diff % 600= 410. c_diff % 3600= 3410. Looping... | |
main(): c_diff % 600= 420. c_diff % 3600= 3420. Looping... | |
main(): c_diff % 600= 430. c_diff % 3600= 3430. Looping... | |
main(): c_diff % 600= 440. c_diff % 3600= 3440. Looping... | |
main(): c_diff % 600= 450. c_diff % 3600= 3450. Looping... | |
main(): c_diff % 600= 460. c_diff % 3600= 3460. Looping... | |
main(): c_diff % 600= 470. c_diff % 3600= 3470. Looping... | |
main(): c_diff % 600= 480. c_diff % 3600= 3480. Looping... | |
main(): c_diff % 600= 490. c_diff % 3600= 3490. Looping... | |
main(): c_diff % 600= 500. c_diff % 3600= 3500. Looping... | |
main(): c_diff % 600= 510. c_diff % 3600= 3510. Looping... | |
main(): c_diff % 600= 520. c_diff % 3600= 3520. Looping... | |
main(): c_diff % 600= 530. c_diff % 3600= 3530. Looping... | |
main(): c_diff % 600= 540. c_diff % 3600= 3540. Looping... | |
main(): c_diff % 600= 550. c_diff % 3600= 3550. Looping... | |
main(): c_diff % 600= 560. c_diff % 3600= 3560. Looping... | |
main(): c_diff % 600= 570. c_diff % 3600= 3570. Looping... | |
main(): c_diff % 600= 580. c_diff % 3600= 3580. Looping... | |
main(): c_diff % 600= 590. c_diff % 3600= 3590. Looping... | |
dt_fm_rtc(): dts= 2024-04-01T01:18:16Z | |
Retrieving data... | |
send_to_pushingbox(): response.status_code= 200 (= OK) | |
set_INT_RTC(): Internal (SYS) RTC is set from NTP service datetime stamp: | |
set_INT_RTC(): 4/01/2024 | |
set_INT_RTC(): 01:18:26 weekday: Monday | |
set_INT_RTC(): Note that NTP weekday starts with 0 | |
main(): c_diff % 600= 20. c_diff % 3600= 20. Looping... | |
main(): c_diff % 600= 30. c_diff % 3600= 30. Looping... | |
main(): c_diff % 600= 40. c_diff % 3600= 40. Looping... | |
[...] | |
Etcetera... | |
CIRCUITPY_WIFI_SSID="<Your SSID>" | |
CIRCUITPY_WIFI_PASSWORD="<Your PASSWORD" | |
ADAFRUIT_IO_USERNAME = "<Your Adafruit IO Username>" # Not needed for example 2 | |
ADAFRUIT_IO_KEY = "<Your Adafruit IO Key>" # Not needed for example 2 | |
timezone= "Europe/Lisbon" # http://worldtimeapi.org/timezones | |
TZ_OFFSET= "1" # Hours | |
COUNTRY="PRT" | |
STATE="" | |
PUSHING_BOX_DEVID= "<Your Pushingbox.com DEVID>" | |
MY_DEBUG = "1" | |
USE_LEDS = "1" | |
USE_SOUND = "1" | |
WAIT_FOR_ZERO_SEC = "1" # line-up time | |
INTERVAL_SECONDS = "3600" # 1 hour - set for a multiple of 60 |
Spreadsheet in: https://docs.google.com/spreadsheets/d/<name>/edit#gid=0 | |
Columns: | |
A: Date_Time | |
B: Temperature | |
C: Humidity | |
D: Data recvd in this sheet at (local) | |
E: Year (formula: =LEFT($A764;4) ) | |
F: Month (formula: =MID($A764;6;2) ) | |
G: Day (formula: =MID($A764;FIND("T";$A764)-2;2) ) | |
H: Time (formula: =MID($A764;FIND("T";$A764)+1;9) ) | |
I: Temp conv & rounded (formula: =MROUND(SUBSTITUTE(SUBSTITUTE(RIGHT($B764;LEN($B764));",";"");".";",");0,005) ) | |
J: Humidity conv & rounded (formula: =MROUND(SUBSTITUTE(SUBSTITUTE(RIGHT($C764;LEN($C764));",";"");".";",");0,005) ) | |
K: Notes |
Note: in the various listings I replaced personal data like WiFi credentials, Pushingbox devid, Google script ID, Google Spreadsheet ID by <name>
or <code>
. You have to replace your own (most in the file: settings.toml).
Annotated image from spreadsheet with data received from MAGTAG via Pushingbox.com and via Google Apps Scripts:
image_ss
On 2024-03-31 added a second example. The first example uses the Adafruit IO time service (through web request) for which we need to supply an adafruit IO username and an adafruit IO password. The second example uses the adafruit_ntp module. For this we don't need any credentials.
Here a link to an image containing the values of temperature & humidity over 96 hours (4 days), interval 1 hour, with average temperature values: temp avg
Google Sheets spreadsheet formula for "last 24 hr avg temp" :
=CONCATENATE("Average temp last 24hr = ";text(sum(I249:I272)/24;"0.00");" degr C)")
Note that since the latest update to the code_using_adafruit_ntp.py
script, this script ran at least 96 hours (4 days) successfully without any interruption.
See: