From 41b42b700e58b2854cfac1bfd1230008496dad34 Mon Sep 17 00:00:00 2001 From: Jonas Scharpf Date: Sat, 30 Jul 2022 20:46:35 +0200 Subject: [PATCH 1/6] add NexRtc class --- nextion/nextion_rtc.py | 212 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 212 insertions(+) create mode 100644 nextion/nextion_rtc.py diff --git a/nextion/nextion_rtc.py b/nextion/nextion_rtc.py new file mode 100644 index 0000000..25138be --- /dev/null +++ b/nextion/nextion_rtc.py @@ -0,0 +1,212 @@ +#!/usr/bin/env python3 +# -*- coding: UTF-8 -*- + +""" +NexRtc + +Functions to interact with Nextion RTC +""" + +# system packages +from time import sleep + +# custom packages +from .common import Common +from .typing import List, Optional, Union + + +class NexRtcError(Exception): + """Base class for exceptions in this module.""" + pass + + +class NexRtc(Common): + """docstring for NexRtc""" + def __init__(self, nh) -> None: + """ + Init RTC + + :param nh: The Nextion hardware interface object + :type nh: NexHardware + """ + super().__init__(nh, pid=-1, cid=-1, name="rtc") + + self._time_types = ["year", "mon", "day", "hour", "min", "sec", "week"] + + @property + def time_types(self) -> List[str]: + """ + Get available time types + + :returns: Requestable time types from RTC + :rtype: List[str] + """ + return self._time_types + + def write_rtc_time(self, *args, **kwargs) -> bool: + """ + Write time to RTC + + :param time: The time to set the RTC + :type time: Union[str, List[int]] + :param time_type: The type of time to change + :type time_type: str + + :returns: True on success, False otherwise + :rtype: bool + """ + if (len(args) + len(kwargs) == 1): + # only a time is given + if len(args): + time = args[0] + else: + time = kwargs["time"] + if isinstance(time, str) and len(time) >= 19: + # "2016,11,25,12,34,50" + year = time[0:4] + month = time[5:7] + day = time[8:10] + hour = time[11:13] + minute = time[14:16] + second = time[17:19] + elif (isinstance(time, list) and + all(isinstance(x, int) for x in time)): + # [2016, 11, 25, 12, 34, 50] + year = time[0] + month = time[1] + day = time[2] + hour = time[3] + minute = time[4] + second = time[5] + else: + raise NexRtcError("Time can either be given as '{}' or '{}'". + format("2016,11,25,12,34,50", + [2016, 11, 25, 12, 34, 50])) + + self._nh._logger.debug("Timestamp (ISO8601): {}-{}-{}T{}:{}:{}". + format(year, month, day, hour, minute, + second)) + + cmd = "rtc0={}".format(year) + self._nh.sendCommand(cmd) + self._nh.recvRetCommandFinished() + + cmd = "rtc1={}".format(month) + self._nh.sendCommand(cmd) + self._nh.recvRetCommandFinished() + + cmd = "rtc2={}".format(day) + self._nh.sendCommand(cmd) + self._nh.recvRetCommandFinished() + + cmd = "rtc3={}".format(hour) + self._nh.sendCommand(cmd) + self._nh.recvRetCommandFinished() + + cmd = "rtc4={}".format(minute) + self._nh.sendCommand(cmd) + self._nh.recvRetCommandFinished() + + cmd = "rtc5={}".format(second) + self._nh.sendCommand(cmd) + return self._nh.recvRetCommandFinished() + elif (len(args) + len(kwargs) == 2): + # time_type is given as well + if len(kwargs) == 2: + time_type = kwargs['time_type'] + time = kwargs['time'] + else: + if len(args) == 2: + time_type = args[0] + time = args[1] + else: + raise NexRtcError("Either use keyword or positional args") + + self._nh._logger.debug("Set '{}' to '{}'".format(time_type, time)) + rtc_index = self.time_types.index(time_type.lower()) + + cmd = "rtc{}={}".format(rtc_index, time) + self._nh.sendCommand(cmd) + return self._nh.recvRetCommandFinished() + else: + raise NexRtcError("Only two args are allowed") + + def read_rtc_time(self, + return_type: str, + length: Optional[int] = 22) -> Union[str, List[int]]: + """ + Read RTC time + + :param return_type: The return type, choose "int", "str" or from + ["year", "mon", "day", "hour", "min", "sec", + "week"] + :type return_type: str + :param length: The length + :type length: Optional[int] + + :returns: RTC time + :rtype: Union[str, List[int]] + """ + return_type = return_type.lower() + + if return_type in ["str", "int"]: + cmd = "get rtc0" + self._nh.sendCommand(cmd) + sleep(0.1) # necessary, data might not be available otherwise + year = self._nh.recvRetNumber() + + cmd = "get rtc1" + self._nh.sendCommand(cmd) + sleep(0.1) # necessary, data might not be available otherwise + month = self._nh.recvRetNumber() + + cmd = "get rtc2" + self._nh.sendCommand(cmd) + sleep(0.1) # necessary, data might not be available otherwise + day = self._nh.recvRetNumber() + + cmd = "get rtc3" + self._nh.sendCommand(cmd) + sleep(0.1) # necessary, data might not be available otherwise + hour = self._nh.recvRetNumber() + + cmd = "get rtc4" + self._nh.sendCommand(cmd) + sleep(0.1) # necessary, data might not be available otherwise + minute = self._nh.recvRetNumber() + + cmd = "get rtc5" + self._nh.sendCommand(cmd) + sleep(0.1) # necessary, data might not be available otherwise + second = self._nh.recvRetNumber() + + cmd = "get rtc6" + self._nh.sendCommand(cmd) + sleep(0.1) # necessary, data might not be available otherwise + week = self._nh.recvRetNumber() + + time_buf = [year, month, day, hour, minute, second, week] + + if return_type == "str": + time_string = ("{}/{}/{} {}:{}:{} {}". + format(year, month, day, hour, minute, second, + week)) + if length >= 22: + return time_string + else: + return time_string[0:length] + elif return_type == "int": + if length >= 7: + return time_buf + else: + return time_buf[0:length] + elif return_type in self.time_types: + rtc_index = self.time_types.index(return_type) + cmd = "get rtc{}".format(rtc_index) + self._nh.sendCommand(cmd) + sleep(0.1) # necessary, data might not be available otherwise + return self._nh.recvRetNumber() + else: + raise NexRtcError("RTC time can only be returned as '{}' or '{}'" + "or chosen from {}". + format("str", "int", self.time_types)) From 80aa13e7357681667853ea4b0ee124eecab94729 Mon Sep 17 00:00:00 2001 From: Jonas Scharpf Date: Sat, 30 Jul 2022 20:46:57 +0200 Subject: [PATCH 2/6] add NexRtc to init file --- nextion/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/nextion/__init__.py b/nextion/__init__.py index 70cbf3a..7078956 100644 --- a/nextion/__init__.py +++ b/nextion/__init__.py @@ -13,6 +13,7 @@ from .nextion_page import NexPage from .nextion_progressbar import NexProgressBar from .nextion_radio import NexRadio +from .nextion_rtc import NexRtc from .nextion_slider import NexSlider from .nextion_text import NexText from .nextion_upload import NexUpload From 0399f9a11bec845af90dd6083f4f0c1aab88ae38 Mon Sep 17 00:00:00 2001 From: Jonas Scharpf Date: Sat, 30 Jul 2022 20:47:47 +0200 Subject: [PATCH 3/6] add example of RTC usage --- examples/rtc/main.py | 100 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 examples/rtc/main.py diff --git a/examples/rtc/main.py b/examples/rtc/main.py new file mode 100644 index 0000000..359d73c --- /dev/null +++ b/examples/rtc/main.py @@ -0,0 +1,100 @@ +#!/usr/bin/env python3 +# -*- coding: UTF-8 -*- + +""" +Main script + +Do your stuff here, this file is similar to the loop() function on Arduino + +Example on how to interact with a RTC +""" + +# system packages +import time + +# custom packages +from nextion import NexHardware, NexRtc + +# define communication pins for Nextion display +tx_pin = 21 +rx_pin = 22 + +# create Nextion hardware interface +nh = NexHardware(rx_pin=rx_pin, tx_pin=tx_pin) + +# init nextion communication interface +nh.nexInit() + +# create a RTC instance +rtc = NexRtc(nh) + +# ============================================================================ +# ============================ Sync time with NTP ============================ +try: + import network + import ntptime + + station = network.WLAN(network.STA_IF) + if station.isconnected(): + ntptime.settime() + else: + print('Device not connected to the internet, using available time') +except Exception as e: + print('Unexpected exception {} occured, using available time'.format(e)) + +# cut off weekday and yearday, keep [year, month, mday, hour, minute, second] +localtime = list(time.localtime())[0:6] + +# ============================================================================ +# ============================ Set RTC functions ============================= +# set RTC time to list of integers '[2022, 7, 30, 18, 21, 45]' +print('Set RTC time to: {}'.format(localtime)) +rtc.write_rtc_time(localtime) +print() + +time.sleep(1) + +# set RTC time to time string '2022,07,30,18,21,45' +localtime_str = ','.join('{:02d}'.format(x) for x in localtime) +print('Set RTC time to: "{}"'.format(localtime_str)) +rtc.write_rtc_time(localtime_str) +print() + +time.sleep(1) + +# set only year of RTC +print('Set only year of RTC to: "{}"'.format(localtime[0])) +rtc.write_rtc_time('year', localtime[0]) +print() + +time.sleep(1) + +# ============================================================================ +# ============================ Get RTC functions ============================= +# get RTC time as string +response = rtc.read_rtc_time('str') +print('Timestamp from RTC as string: "{}"'.format(response)) +print() + +time.sleep(1) + +# get RTC time as list of integers +response = rtc.read_rtc_time('int') +print('Timestamp from RTC list of integers: "{}"'.format(response)) +print() + +time.sleep(1) + +# get available time types from RTC one by one +print('Get individual time types from RTC...') +for time_type in rtc.time_types: + response = rtc.read_rtc_time(time_type) + print('{} by RTC: "{}"'.format(time_type, response)) +print() + +# ============================================================================ +# ============================= End of example =============================== +print('Returning to REPL in 5 seconds') + +# wait for 5 more seconds to safely finish the may still running threads +time.sleep(5) From 055f0199bfe2820dbd17fbea591bf7a2fc518d52 Mon Sep 17 00:00:00 2001 From: Jonas Scharpf Date: Sat, 30 Jul 2022 20:48:21 +0200 Subject: [PATCH 4/6] mark RTC as supported in example README file --- examples/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/README.md b/examples/README.md index 0483e54..32f6d46 100644 --- a/examples/README.md +++ b/examples/README.md @@ -15,7 +15,7 @@ | [Picture](picture) | NexPicture | :x: | | [Progress](progress) | NexProgress | :heavy_check_mark: | | [Radio](radio) | NexRadio | :heavy_check_mark: | -| [Rtc](rtc) | NexRtc | :x: | +| [Rtc](rtc) | NexRtc | :heavy_check_mark: | | [Scrolltext](scrolltext) | NexScrolltext | :x: | | [Slider](slider) | NexSlider | :heavy_check_mark: | | [Text](text) | NexText | :heavy_check_mark: | From 741efb02b96a4f10c5a86ea94f34bda03c7256a4 Mon Sep 17 00:00:00 2001 From: Jonas Scharpf Date: Sat, 30 Jul 2022 20:49:24 +0200 Subject: [PATCH 5/6] add missing docs for upload example to examples README --- examples/README.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/examples/README.md b/examples/README.md index 32f6d46..c4d2fc2 100644 --- a/examples/README.md +++ b/examples/README.md @@ -36,3 +36,21 @@ elements by simple UART command calls. The [hardware example](hardware/main.py) shows the usage of the hardware functions `sleep`, `brightness` and `reset`. + +## Upload example + +The [upload example](upload/main.py) shows how to update a Nextion display +with a new TFT file. + +Copy the [example TFT file](everything.tft) to the MicroPython board with +e.g. `rshell` + +```bash +rshell --port /dev/tty.SLAB_USBtoUART --editor nano +``` + +Copy the file to the device, this might take several minutes! + +```bash +cp everything.tft /pyboard +``` From 8898ae92c9199829c204208c13c7de83d411abe2 Mon Sep 17 00:00:00 2001 From: Jonas Scharpf Date: Sat, 30 Jul 2022 20:50:50 +0200 Subject: [PATCH 6/6] update changelog for 0.12.0 --- changelog.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/changelog.md b/changelog.md index 41a2a18..bd7a973 100644 --- a/changelog.md +++ b/changelog.md @@ -17,6 +17,14 @@ r"^\#\# \[\d{1,}[.]\d{1,}[.]\d{1,}\] \- \d{4}\-\d{2}-\d{2}$" --> ## Released +## [0.12.0] - 2022-07-30 +### Added +- Support `NexRtc` usage with [`nextion_rtc`](nextion/nextion_rtc.py) + +### Fixed +- Add missing documentation for [upload example](examples/upload/main.py) to + [examples README](examples/) + ## [0.11.0] - 2022-07-30 ### Added - Support `NexUpload` usage with [`nextion_upload`](nextion/nextion_upload.py) @@ -156,8 +164,9 @@ r"^\#\# \[\d{1,}[.]\d{1,}[.]\d{1,}\] \- \d{4}\-\d{2}-\d{2}$" - [Example HMI file](examples/everything.HMI) to be used for all examples -[Unreleased]: https://github.com/brainelectronics/micropython-nextion/compare/0.11.0...develop +[Unreleased]: https://github.com/brainelectronics/micropython-nextion/compare/0.12.0...develop +[0.12.0]: https://github.com/brainelectronics/micropython-nextion/tree/0.12.0 [0.11.0]: https://github.com/brainelectronics/micropython-nextion/tree/0.11.0 [0.10.0]: https://github.com/brainelectronics/micropython-nextion/tree/0.10.0 [0.9.0]: https://github.com/brainelectronics/micropython-nextion/tree/0.9.0