Skip to content

Instantly share code, notes, and snippets.

@PaulskPt
Last active April 8, 2024 11:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save PaulskPt/86551032942e760910b0fb7fa6e2a1bb to your computer and use it in GitHub Desktop.
Save PaulskPt/86551032942e760910b0fb7fa6e2a1bb to your computer and use it in GitHub Desktop.
Data_to_Google
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
@PaulskPt
Copy link
Author

@PaulskPt
Copy link
Author

PaulskPt commented Mar 24, 2024

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).

@PaulskPt
Copy link
Author

Annotated image from spreadsheet with data received from MAGTAG via Pushingbox.com and via Google Apps Scripts:
image_ss

@PaulskPt
Copy link
Author

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.

@PaulskPt
Copy link
Author

PaulskPt commented Apr 8, 2024

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

@PaulskPt
Copy link
Author

PaulskPt commented Apr 8, 2024

Google Sheets spreadsheet formula for "last 24 hr avg temp" :
=CONCATENATE("Average temp last 24hr = ";text(sum(I249:I272)/24;"0.00");" degr C)")

@PaulskPt
Copy link
Author

PaulskPt commented Apr 8, 2024

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment